[Mesa-dev] [PATCH 09/10] mesa: Factor out struct gl_vertex_format.

Brian Paul brianp at vmware.com
Sun Nov 18 19:54:50 UTC 2018


The series looks great.  Just a few minor things below.

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


On 11/17/2018 05:14 AM, Mathias.Froehlich at gmx.net wrote:
> From: Mathias Fröhlich <mathias.froehlich at web.de>
> 
> Factor out struct gl_vertex_format from array attributes.
> The data type is supposed to describe the type of a vertex
> element. At this current stage the data type is only used
> with the VAO, but actually is useful in various other places.
> Due to the bitfields being used, special care needs to be
> taken for the glGet code paths.
> 
> Signed-off-by: Mathias Fröhlich <Mathias.Froehlich at web.de>
> ---
>   src/mesa/drivers/dri/i965/brw_context.h       |  2 +-
>   src/mesa/drivers/dri/i965/brw_draw.c          | 14 ++--
>   src/mesa/drivers/dri/i965/brw_draw_upload.c   | 60 ++++++++---------
>   src/mesa/drivers/dri/i965/genX_state_upload.c | 14 ++--
>   src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c  | 10 +--
>   src/mesa/main/api_arrayelt.c                  | 34 +++++-----
>   src/mesa/main/arrayobj.c                      | 21 +++---
>   src/mesa/main/draw.c                          | 13 ++--
>   src/mesa/main/get.c                           | 15 ++++-
>   src/mesa/main/get_hash_params.py              | 20 +++---
>   src/mesa/main/mtypes.h                        | 27 +++++---
>   src/mesa/main/varray.c                        | 64 ++++++++++---------
>   src/mesa/main/varray.h                        | 20 ++++++
>   src/mesa/state_tracker/st_atom.h              |  2 +-
>   src/mesa/state_tracker/st_atom_array.c        | 28 ++++----
>   src/mesa/state_tracker/st_draw_feedback.c     |  2 +-
>   src/mesa/tnl/t_draw.c                         | 22 +++----
>   src/mesa/tnl/t_split_copy.c                   | 18 ++----
>   src/mesa/vbo/vbo_context.c                    |  5 +-
>   src/mesa/vbo/vbo_exec_api.c                   | 13 ++--
>   src/mesa/vbo/vbo_private.h                    | 10 +++
>   src/mesa/vbo/vbo_save_api.c                   | 12 ++--
>   src/mesa/vbo/vbo_save_draw.c                  | 14 ++--
>   src/mesa/vbo/vbo_save_loopback.c              |  2 +-
>   24 files changed, 239 insertions(+), 203 deletions(-)
> 
> diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
> index 7fd15669eb..e5d57dd8df 100644
> --- a/src/mesa/drivers/dri/i965/brw_context.h
> +++ b/src/mesa/drivers/dri/i965/brw_context.h
> @@ -1493,7 +1493,7 @@ gl_clip_plane *brw_select_clip_planes(struct gl_context *ctx);
>   
>   /* brw_draw_upload.c */
>   unsigned brw_get_vertex_surface_type(struct brw_context *brw,
> -                                     const struct gl_array_attributes *glattr);
> +                                     const struct gl_vertex_format *glformat);
>   
>   static inline unsigned
>   brw_get_index_type(unsigned index_size)
> diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c
> index 8536c04010..f080a9fefc 100644
> --- a/src/mesa/drivers/dri/i965/brw_draw.c
> +++ b/src/mesa/drivers/dri/i965/brw_draw.c
> @@ -303,16 +303,16 @@ brw_merge_inputs(struct brw_context *brw)
>          * 2_10_10_10_REV vertex formats.  Set appropriate workaround flags.
>          */
>         while (mask) {
> -         const struct gl_array_attributes *glattrib;
> +         const struct gl_vertex_format *glformat;
>            uint8_t wa_flags = 0;
>   
>            i = u_bit_scan64(&mask);
> -         glattrib = brw->vb.inputs[i].glattrib;
> +         glformat = &brw->vb.inputs[i].glattrib->Format;
>   
> -         switch (glattrib->Type) {
> +         switch (glformat->Type) {
>   
>            case GL_FIXED:
> -            wa_flags = glattrib->Size;
> +            wa_flags = glformat->Size;
>               break;
>   
>            case GL_INT_2_10_10_10_REV:
> @@ -320,12 +320,12 @@ brw_merge_inputs(struct brw_context *brw)
>               /* fallthough */
>   
>            case GL_UNSIGNED_INT_2_10_10_10_REV:
> -            if (glattrib->Format == GL_BGRA)
> +            if (glformat->Format == GL_BGRA)
>                  wa_flags |= BRW_ATTRIB_WA_BGRA;
>   
> -            if (glattrib->Normalized)
> +            if (glformat->Normalized)
>                  wa_flags |= BRW_ATTRIB_WA_NORMALIZE;
> -            else if (!glattrib->Integer)
> +            else if (!glformat->Integer)
>                  wa_flags |= BRW_ATTRIB_WA_SCALE;
>   
>               break;
> diff --git a/src/mesa/drivers/dri/i965/brw_draw_upload.c b/src/mesa/drivers/dri/i965/brw_draw_upload.c
> index dc3022bc41..dfbc45fe93 100644
> --- a/src/mesa/drivers/dri/i965/brw_draw_upload.c
> +++ b/src/mesa/drivers/dri/i965/brw_draw_upload.c
> @@ -249,21 +249,21 @@ double_types(int size, GLboolean doubles)
>    */
>   unsigned
>   brw_get_vertex_surface_type(struct brw_context *brw,
> -                            const struct gl_array_attributes *glattrib)
> +                            const struct gl_vertex_format *glformat)
>   {
> -   int size = glattrib->Size;
> +   int size = glformat->Size;
>      const struct gen_device_info *devinfo = &brw->screen->devinfo;
>      const bool is_ivybridge_or_older =
>         devinfo->gen <= 7 && !devinfo->is_baytrail && !devinfo->is_haswell;
>   
>      if (unlikely(INTEL_DEBUG & DEBUG_VERTS))
>         fprintf(stderr, "type %s size %d normalized %d\n",
> -              _mesa_enum_to_string(glattrib->Type),
> -              glattrib->Size, glattrib->Normalized);
> +              _mesa_enum_to_string(glformat->Type),
> +              glformat->Size, glformat->Normalized);
>   
> -   if (glattrib->Integer) {
> -      assert(glattrib->Format == GL_RGBA); /* sanity check */
> -      switch (glattrib->Type) {
> +   if (glformat->Integer) {
> +      assert(glformat->Format == GL_RGBA); /* sanity check */
> +      switch (glformat->Type) {
>         case GL_INT: return int_types_direct[size];
>         case GL_SHORT:
>            if (is_ivybridge_or_older && size == 3)
> @@ -288,11 +288,11 @@ brw_get_vertex_surface_type(struct brw_context *brw,
>               return ubyte_types_direct[size];
>         default: unreachable("not reached");
>         }
> -   } else if (glattrib->Type == GL_UNSIGNED_INT_10F_11F_11F_REV) {
> +   } else if (glformat->Type == GL_UNSIGNED_INT_10F_11F_11F_REV) {
>         return ISL_FORMAT_R11G11B10_FLOAT;
> -   } else if (glattrib->Normalized) {
> -      switch (glattrib->Type) {
> -      case GL_DOUBLE: return double_types(size, glattrib->Doubles);
> +   } else if (glformat->Normalized) {
> +      switch (glformat->Type) {
> +      case GL_DOUBLE: return double_types(size, glformat->Doubles);
>         case GL_FLOAT: return float_types[size];
>         case GL_HALF_FLOAT:
>         case GL_HALF_FLOAT_OES:
> @@ -306,7 +306,7 @@ brw_get_vertex_surface_type(struct brw_context *brw,
>         case GL_UNSIGNED_INT: return uint_types_norm[size];
>         case GL_UNSIGNED_SHORT: return ushort_types_norm[size];
>         case GL_UNSIGNED_BYTE:
> -         if (glattrib->Format == GL_BGRA) {
> +         if (glformat->Format == GL_BGRA) {
>               /* See GL_EXT_vertex_array_bgra */
>               assert(size == 4);
>               return ISL_FORMAT_B8G8R8A8_UNORM;
> @@ -330,7 +330,7 @@ brw_get_vertex_surface_type(struct brw_context *brw,
>         case GL_INT_2_10_10_10_REV:
>            assert(size == 4);
>            if (devinfo->gen >= 8 || devinfo->is_haswell) {
> -            return glattrib->Format == GL_BGRA
> +            return glformat->Format == GL_BGRA
>                  ? ISL_FORMAT_B10G10R10A2_SNORM
>                  : ISL_FORMAT_R10G10B10A2_SNORM;
>            }
> @@ -338,7 +338,7 @@ brw_get_vertex_surface_type(struct brw_context *brw,
>         case GL_UNSIGNED_INT_2_10_10_10_REV:
>            assert(size == 4);
>            if (devinfo->gen >= 8 || devinfo->is_haswell) {
> -            return glattrib->Format == GL_BGRA
> +            return glformat->Format == GL_BGRA
>                  ? ISL_FORMAT_B10G10R10A2_UNORM
>                  : ISL_FORMAT_R10G10B10A2_UNORM;
>            }
> @@ -352,26 +352,26 @@ brw_get_vertex_surface_type(struct brw_context *brw,
>          * like to use here, so upload everything as UINT and fix
>          * it in the shader
>          */
> -      if (glattrib->Type == GL_INT_2_10_10_10_REV) {
> +      if (glformat->Type == GL_INT_2_10_10_10_REV) {
>            assert(size == 4);
>            if (devinfo->gen >= 8 || devinfo->is_haswell) {
> -            return glattrib->Format == GL_BGRA
> +            return glformat->Format == GL_BGRA
>                  ? ISL_FORMAT_B10G10R10A2_SSCALED
>                  : ISL_FORMAT_R10G10B10A2_SSCALED;
>            }
>            return ISL_FORMAT_R10G10B10A2_UINT;
> -      } else if (glattrib->Type == GL_UNSIGNED_INT_2_10_10_10_REV) {
> +      } else if (glformat->Type == GL_UNSIGNED_INT_2_10_10_10_REV) {
>            assert(size == 4);
>            if (devinfo->gen >= 8 || devinfo->is_haswell) {
> -            return glattrib->Format == GL_BGRA
> +            return glformat->Format == GL_BGRA
>                  ? ISL_FORMAT_B10G10R10A2_USCALED
>                  : ISL_FORMAT_R10G10B10A2_USCALED;
>            }
>            return ISL_FORMAT_R10G10B10A2_UINT;
>         }
> -      assert(glattrib->Format == GL_RGBA); /* sanity check */
> -      switch (glattrib->Type) {
> -      case GL_DOUBLE: return double_types(size, glattrib->Doubles);
> +      assert(glformat->Format == GL_RGBA); /* sanity check */
> +      switch (glformat->Type) {
> +      case GL_DOUBLE: return double_types(size, glformat->Doubles);
>         case GL_FLOAT: return float_types[size];
>         case GL_HALF_FLOAT:
>         case GL_HALF_FLOAT_OES:
> @@ -407,6 +407,7 @@ copy_array_to_vbo_array(struct brw_context *brw,
>   {
>      const struct gl_vertex_buffer_binding *glbinding = element->glbinding;
>      const struct gl_array_attributes *glattrib = element->glattrib;
> +   const struct gl_vertex_format *glformat = &glattrib->Format;
>      const int src_stride = glbinding->Stride;
>   
>      /* If the source stride is zero, we just want to upload the current
> @@ -414,11 +415,11 @@ copy_array_to_vbo_array(struct brw_context *brw,
>       * to replicate it out.
>       */
>      if (src_stride == 0) {
> -      brw_upload_data(&brw->upload, glattrib->Ptr, glattrib->_ElementSize,
> -                      glattrib->_ElementSize, &buffer->bo, &buffer->offset);
> +      brw_upload_data(&brw->upload, glattrib->Ptr, glformat->_ElementSize,
> +                      glformat->_ElementSize, &buffer->bo, &buffer->offset);
>   
>         buffer->stride = 0;
> -      buffer->size = glattrib->_ElementSize;
> +      buffer->size = glformat->_ElementSize;
>         return;
>      }
>   
> @@ -531,13 +532,13 @@ brw_prepare_vertices(struct brw_context *brw)
>                  start = offset + glbinding->Stride * brw->baseinstance;
>                  range = (glbinding->Stride * ((brw->num_instances - 1) /
>                                               glbinding->InstanceDivisor) +
> -                        glattrib->_ElementSize);
> +                        glattrib->Format._ElementSize);
>               }
>            } else {
>               if (brw->vb.index_bounds_valid) {
>                  start = offset + min_index * glbinding->Stride;
>                  range = (glbinding->Stride * (max_index - min_index) +
> -                        glattrib->_ElementSize);
> +                        glattrib->Format._ElementSize);
>               }
>            }
>   
> @@ -594,7 +595,8 @@ brw_prepare_vertices(struct brw_context *brw)
>   	 else if (interleaved != glbinding->Stride ||
>                     glbinding->InstanceDivisor != 0 ||
>                     glattrib->Ptr < ptr ||
> -                  (uintptr_t)(glattrib->Ptr - ptr) + glattrib->_ElementSize > interleaved)
> +                  (uintptr_t)(glattrib->Ptr - ptr) +
> +                  glattrib->Format._ElementSize > interleaved)
>   	 {
>               /* If our stride is different from the first attribute's stride,
>                * or if we are using an instance divisor or if the first
> @@ -677,7 +679,7 @@ brw_prepare_vertices(struct brw_context *brw)
>         const struct gl_array_attributes *glattrib = upload[i]->glattrib;
>         if (glbinding->InstanceDivisor == 0) {
>            copy_array_to_vbo_array(brw, upload[i], min_index, max_index,
> -                                 buffer, glattrib->_ElementSize);
> +                                 buffer, glattrib->Format._ElementSize);
>         } else {
>            /* This is an instanced attribute, since its InstanceDivisor
>             * is not zero. Therefore, its data will be stepped after the
> @@ -686,7 +688,7 @@ brw_prepare_vertices(struct brw_context *brw)
>            uint32_t instanced_attr_max_index =
>               (brw->num_instances - 1) / glbinding->InstanceDivisor;
>            copy_array_to_vbo_array(brw, upload[i], 0, instanced_attr_max_index,
> -                                 buffer, glattrib->_ElementSize);
> +                                 buffer, glattrib->Format._ElementSize);
>         }
>         buffer->offset -= delta * buffer->stride;
>         buffer->size += delta * buffer->stride;
> diff --git a/src/mesa/drivers/dri/i965/genX_state_upload.c b/src/mesa/drivers/dri/i965/genX_state_upload.c
> index 5acd092292..8e3fcbf12e 100644
> --- a/src/mesa/drivers/dri/i965/genX_state_upload.c
> +++ b/src/mesa/drivers/dri/i965/genX_state_upload.c
> @@ -620,7 +620,7 @@ genX(emit_vertices)(struct brw_context *brw)
>      for (unsigned i = 0; i < brw->vb.nr_enabled; i++) {
>         struct brw_vertex_element *input = brw->vb.enabled[i];
>         const struct gl_array_attributes *glattrib = input->glattrib;
> -      uint32_t format = brw_get_vertex_surface_type(brw, glattrib);
> +      uint32_t format = brw_get_vertex_surface_type(brw, &glattrib->Format);
>   
>         if (uploads_needed(format, input->is_dual_slot) > 1)
>            nr_elements++;
> @@ -713,7 +713,7 @@ genX(emit_vertices)(struct brw_context *brw)
>      for (i = 0; i < brw->vb.nr_enabled; i++) {
>         const struct brw_vertex_element *input = brw->vb.enabled[i];
>         const struct gl_array_attributes *glattrib = input->glattrib;
> -      uint32_t format = brw_get_vertex_surface_type(brw, glattrib);
> +      uint32_t format = brw_get_vertex_surface_type(brw, &glattrib->Format);
>         uint32_t comp0 = VFCOMP_STORE_SRC;
>         uint32_t comp1 = VFCOMP_STORE_SRC;
>         uint32_t comp2 = VFCOMP_STORE_SRC;
> @@ -756,16 +756,16 @@ genX(emit_vertices)(struct brw_context *brw)
>   
>            const struct gl_array_attributes *glattrib = input->glattrib;
>            const int size = (GEN_GEN < 8 && is_passthru_format(format)) ?
> -            upload_format_size(upload_format) : glattrib->Size;
> +            upload_format_size(upload_format) : glattrib->Format.Size;
>   
>            switch (size) {
>               case 0: comp0 = VFCOMP_STORE_0;
>               case 1: comp1 = VFCOMP_STORE_0;
>               case 2: comp2 = VFCOMP_STORE_0;
>               case 3:
> -               if (GEN_GEN >= 8 && glattrib->Doubles) {
> +               if (GEN_GEN >= 8 && glattrib->Format.Doubles) {
>                     comp3 = VFCOMP_STORE_0;
> -               } else if (glattrib->Integer) {
> +               } else if (glattrib->Format.Integer) {
>                     comp3 = VFCOMP_STORE_1_INT;
>                  } else {
>                     comp3 = VFCOMP_STORE_1_FP;
> @@ -790,7 +790,7 @@ genX(emit_vertices)(struct brw_context *brw)
>             *     to be specified as VFCOMP_STORE_0 in order to output a 256-bit
>             *     vertex element."
>             */
> -         if (glattrib->Doubles && !input->is_dual_slot) {
> +         if (glattrib->Format.Doubles && !input->is_dual_slot) {
>               /* Store vertex elements which correspond to double and dvec2 vertex
>                * shader inputs as 128-bit vertex elements, instead of 256-bits.
>                */
> @@ -877,7 +877,7 @@ genX(emit_vertices)(struct brw_context *brw)
>   #if GEN_GEN >= 6
>      if (gen6_edgeflag_input) {
>         const struct gl_array_attributes *glattrib = gen6_edgeflag_input->glattrib;
> -      const uint32_t format = brw_get_vertex_surface_type(brw, glattrib);
> +      const uint32_t format = brw_get_vertex_surface_type(brw, &glattrib->Format);
>   
>         struct GENX(VERTEX_ELEMENT_STATE) elem_state = {
>            .Valid = true,
> diff --git a/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c b/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c
> index 97ff07808b..f037bd2015 100644
> --- a/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c
> +++ b/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c
> @@ -49,7 +49,7 @@ get_array_stride(struct gl_context *ctx, const struct tnl_vertex_array *a)
>   	if (render->mode == VBO && !_mesa_is_bufferobj(binding->BufferObj)) {
>   		const struct gl_array_attributes *attrib = a->VertexAttrib;
>   		/* Pack client buffers. */
> -		return align(attrib->_ElementSize, 4);
> +		return align(attrib->Format._ElementSize, 4);
>   	} else {
>   		return binding->Stride;
>   	}
> @@ -86,7 +86,7 @@ vbo_init_arrays(struct gl_context *ctx, const struct _mesa_index_buffer *ib,
>   
>   		nouveau_init_array(&render->attrs[attr], attr,
>   				   get_array_stride(ctx, array),
> -				   attrib->Size, attrib->Type,
> +				   attrib->Format.Size, attrib->Format.Type,
>   				   imm ? binding->BufferObj : NULL,
>   				   p, imm, ctx);
>   	}
> @@ -154,8 +154,8 @@ vbo_emit_attr(struct gl_context *ctx, const struct tnl_vertex_array *arrays,
>   			return;
>   
>   		/* Constant attribute. */
> -		nouveau_init_array(a, attr, binding->Stride, attrib->Size,
> -				   attrib->Type, binding->BufferObj, p,
> +		nouveau_init_array(a, attr, binding->Stride, attrib->Format.Size,
> +				   attrib->Format.Type, binding->BufferObj, p,
>   				   GL_TRUE, ctx);
>   		EMIT_IMM(ctx, a, 0);
>   		nouveau_deinit_array(a);
> @@ -166,7 +166,7 @@ vbo_emit_attr(struct gl_context *ctx, const struct tnl_vertex_array *arrays,
>   
>   		if (render->mode == VBO) {
>   			render->map[info->vbo_index] = attr;
> -			render->vertex_size += attrib->_ElementSize;
> +			render->vertex_size += attrib->Format._ElementSize;
>   			render->attr_count = MAX2(render->attr_count,
>   						  info->vbo_index + 1);
>   		} else {
> diff --git a/src/mesa/main/api_arrayelt.c b/src/mesa/main/api_arrayelt.c
> index 25cbc5326f..2b59c478d9 100644
> --- a/src/mesa/main/api_arrayelt.c
> +++ b/src/mesa/main/api_arrayelt.c
> @@ -1575,7 +1575,7 @@ _ae_update_state(struct gl_context *ctx)
>      if (vao->Enabled & VERT_BIT_COLOR_INDEX) {
>         aa->array = &vao->VertexAttrib[VERT_ATTRIB_COLOR_INDEX];
>         aa->binding = &vao->BufferBinding[aa->array->BufferBindingIndex];
> -      aa->offset = IndexFuncs[TYPE_IDX(aa->array->Type)];
> +      aa->offset = IndexFuncs[TYPE_IDX(aa->array->Format.Type)];
>         check_vbo(actx, aa->binding->BufferObj);
>         aa++;
>      }
> @@ -1591,7 +1591,7 @@ _ae_update_state(struct gl_context *ctx)
>      if (vao->Enabled & VERT_BIT_NORMAL) {
>         aa->array = &vao->VertexAttrib[VERT_ATTRIB_NORMAL];
>         aa->binding = &vao->BufferBinding[aa->array->BufferBindingIndex];
> -      aa->offset = NormalFuncs[TYPE_IDX(aa->array->Type)];
> +      aa->offset = NormalFuncs[TYPE_IDX(aa->array->Format.Type)];
>         check_vbo(actx, aa->binding->BufferObj);
>         aa++;
>      }
> @@ -1599,7 +1599,7 @@ _ae_update_state(struct gl_context *ctx)
>      if (vao->Enabled & VERT_BIT_COLOR0) {
>         aa->array = &vao->VertexAttrib[VERT_ATTRIB_COLOR0];
>         aa->binding = &vao->BufferBinding[aa->array->BufferBindingIndex];
> -      aa->offset = ColorFuncs[aa->array->Size-3][TYPE_IDX(aa->array->Type)];
> +      aa->offset = ColorFuncs[aa->array->Format.Size-3][TYPE_IDX(aa->array->Format.Type)];
>         check_vbo(actx, aa->binding->BufferObj);
>         aa++;
>      }
> @@ -1607,7 +1607,7 @@ _ae_update_state(struct gl_context *ctx)
>      if (vao->Enabled & VERT_BIT_COLOR1) {
>         aa->array = &vao->VertexAttrib[VERT_ATTRIB_COLOR1];
>         aa->binding = &vao->BufferBinding[aa->array->BufferBindingIndex];
> -      aa->offset = SecondaryColorFuncs[TYPE_IDX(aa->array->Type)];
> +      aa->offset = SecondaryColorFuncs[TYPE_IDX(aa->array->Format.Type)];
>         check_vbo(actx, aa->binding->BufferObj);
>         aa++;
>      }
> @@ -1615,7 +1615,7 @@ _ae_update_state(struct gl_context *ctx)
>      if (vao->Enabled & VERT_BIT_FOG) {
>         aa->array = &vao->VertexAttrib[VERT_ATTRIB_FOG];
>         aa->binding = &vao->BufferBinding[aa->array->BufferBindingIndex];
> -      aa->offset = FogCoordFuncs[TYPE_IDX(aa->array->Type)];
> +      aa->offset = FogCoordFuncs[TYPE_IDX(aa->array->Format.Type)];
>         check_vbo(actx, aa->binding->BufferObj);
>         aa++;
>      }
> @@ -1629,10 +1629,10 @@ _ae_update_state(struct gl_context *ctx)
>             */
>            at->array = attribArray;
>            at->binding = &vao->BufferBinding[attribArray->BufferBindingIndex];
> -         assert(!at->array->Normalized);
> -         at->func = AttribFuncsNV[at->array->Normalized]
> -                                 [at->array->Size-1]
> -                                 [TYPE_IDX(at->array->Type)];
> +         assert(!at->array->Format.Normalized);
> +         at->func = AttribFuncsNV[at->array->Format.Normalized]
> +                                 [at->array->Format.Size-1]
> +                                 [TYPE_IDX(at->array->Format.Type)];
>            at->index = VERT_ATTRIB_TEX0 + i;
>   	 check_vbo(actx, at->binding->BufferObj);
>            at++;
> @@ -1652,18 +1652,18 @@ _ae_update_state(struct gl_context *ctx)
>             * change from one execution of _ae_ArrayElement() to
>             * the next.  Doing so caused UT to break.
>             */
> -         if (at->array->Doubles)
> +         if (at->array->Format.Doubles)
>               intOrNorm = 3;
> -         else if (at->array->Integer)
> +         else if (at->array->Format.Integer)
>               intOrNorm = 2;
> -         else if (at->array->Normalized)
> +         else if (at->array->Format.Normalized)
>               intOrNorm = 1;
>            else
>               intOrNorm = 0;
>   
>            at->func = AttribFuncsARB[intOrNorm]
> -            [at->array->Size-1]
> -            [TYPE_IDX(at->array->Type)];
> +            [at->array->Format.Size-1]
> +            [TYPE_IDX(at->array->Format.Type)];
>   
>            at->index = i;
>   	 check_vbo(actx, at->binding->BufferObj);
> @@ -1678,15 +1678,15 @@ _ae_update_state(struct gl_context *ctx)
>          */
>         aa->array = &vao->VertexAttrib[VERT_ATTRIB_GENERIC0];
>         aa->binding = &vao->BufferBinding[aa->array->BufferBindingIndex];
> -      assert(aa->array->Size >= 2); /* XXX fix someday? */
> -      aa->offset = VertexFuncs[aa->array->Size-2][TYPE_IDX(aa->array->Type)];
> +      assert(aa->array->Format.Size >= 2); /* XXX fix someday? */
> +      aa->offset = VertexFuncs[aa->array->Format.Size-2][TYPE_IDX(aa->array->Format.Type)];
>         check_vbo(actx, aa->binding->BufferObj);
>         aa++;
>      }
>      else if (vao->Enabled & VERT_BIT_POS) {
>         aa->array = &vao->VertexAttrib[VERT_ATTRIB_POS];
>         aa->binding = &vao->BufferBinding[aa->array->BufferBindingIndex];
> -      aa->offset = VertexFuncs[aa->array->Size-2][TYPE_IDX(aa->array->Type)];
> +      aa->offset = VertexFuncs[aa->array->Format.Size-2][TYPE_IDX(aa->array->Format.Type)];
>         check_vbo(actx, aa->binding->BufferObj);
>         aa++;
>      }
> diff --git a/src/mesa/main/arrayobj.c b/src/mesa/main/arrayobj.c
> index f80bf2c949..bfd6fce679 100644
> --- a/src/mesa/main/arrayobj.c
> +++ b/src/mesa/main/arrayobj.c
> @@ -385,22 +385,17 @@ init_array(struct gl_context *ctx,
>      assert(index < ARRAY_SIZE(vao->BufferBinding));
>      struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[index];
>   
> -   array->Size = size;
> -   array->Type = type;
> -   array->Format = GL_RGBA; /* only significant for GL_EXT_vertex_array_bgra */
> +   _mesa_set_vertex_format(&array->Format, size, type, GL_RGBA,
> +                           GL_FALSE, GL_FALSE, GL_FALSE);
>      array->Stride = 0;
>      array->Ptr = NULL;
>      array->RelativeOffset = 0;
> -   array->Normalized = GL_FALSE;
> -   array->Integer = GL_FALSE;
> -   array->Doubles = GL_FALSE;
> -   array->_ElementSize = size * _mesa_sizeof_type(type);
>      ASSERT_BITFIELD_SIZE(struct gl_array_attributes, BufferBindingIndex,
>                           VERT_ATTRIB_MAX - 1);
>      array->BufferBindingIndex = index;
>   
>      binding->Offset = 0;
> -   binding->Stride = array->_ElementSize;
> +   binding->Stride = array->Format._ElementSize;
>      binding->BufferObj = NULL;
>      binding->_BoundArrays = BITFIELD_BIT(index);
>   
> @@ -756,7 +751,7 @@ _mesa_update_vao_derived_arrays(struct gl_context *ctx,
>            GLbitfield eff_bound_arrays = bound;
>   
>            const GLubyte *ptr = attrib->Ptr;
> -         unsigned vertex_end = attrib->_ElementSize;
> +         unsigned vertex_end = attrib->Format._ElementSize;
>   
>            /* Walk other user space arrays and see which are interleaved
>             * using the same binding parameters.
> @@ -778,9 +773,10 @@ _mesa_update_vao_derived_arrays(struct gl_context *ctx,
>               if (binding->InstanceDivisor != binding2->InstanceDivisor)
>                  continue;
>               if (ptr <= attrib2->Ptr) {
> -               if (ptr + binding->Stride < attrib2->Ptr + attrib2->_ElementSize)
> +               if (ptr + binding->Stride < attrib2->Ptr +
> +                   attrib2->Format._ElementSize)
>                     continue;
> -               unsigned end = attrib2->Ptr + attrib2->_ElementSize - ptr;
> +               unsigned end = attrib2->Ptr + attrib2->Format._ElementSize - ptr;
>                  vertex_end = MAX2(vertex_end, end);
>               } else {
>                  if (attrib2->Ptr + binding->Stride < ptr + vertex_end)
> @@ -823,7 +819,8 @@ _mesa_update_vao_derived_arrays(struct gl_context *ctx,
>         /* Query the original api defined attrib/binding information ... */
>         const unsigned char *const map =_mesa_vao_attribute_map[mode];
>         if (vao->Enabled & VERT_BIT(map[attr])) {
> -         const struct gl_array_attributes *attrib = &vao->VertexAttrib[map[attr]];
> +         const struct gl_array_attributes *attrib =
> +            &vao->VertexAttrib[map[attr]];
>            const struct gl_vertex_buffer_binding *binding =
>               &vao->BufferBinding[attrib->BufferBindingIndex];
>            /* ... and compare that with the computed attrib/binding */
> diff --git a/src/mesa/main/draw.c b/src/mesa/main/draw.c
> index 313df6aa8b..bfc4b9c937 100644
> --- a/src/mesa/main/draw.c
> +++ b/src/mesa/main/draw.c
> @@ -82,18 +82,19 @@ check_array_data(struct gl_context *ctx, struct gl_vertex_array_object *vao,
>            data = ADD_POINTERS(_mesa_vertex_attrib_address(array, binding),
>                                bo->Mappings[MAP_INTERNAL].Pointer);
>         }
> -      switch (array->Type) {
> +      switch (array->Format.Type) {
>         case GL_FLOAT:
>            {
>               GLfloat *f = (GLfloat *) ((GLubyte *) data + binding->Stride * j);
>               GLint k;
> -            for (k = 0; k < array->Size; k++) {
> +            for (k = 0; k < array->Format.Size; k++) {
>                  if (IS_INF_OR_NAN(f[k]) || f[k] >= 1.0e20F || f[k] <= -1.0e10F) {
>                     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, binding->Stride);
> +                         array->Format.Type, array->Format.Size,
> +                         binding->Stride);
>                     printf("  Address/offset %p in Buffer Object %u\n",
>                            array->Ptr, bo->Name);
>                     f[k] = 1.0F;  /* XXX replace the bad value! */
> @@ -288,7 +289,7 @@ print_draw_arrays(struct gl_context *ctx,
>         printf("attr %s: size %d stride %d  "
>                "ptr %p  Bufobj %u\n",
>                gl_vert_attrib_name((gl_vert_attrib) i),
> -             array->Size, binding->Stride,
> +             array->Format.Size, binding->Stride,
>                array->Ptr, bufObj->Name);
>   
>         if (_mesa_is_bufferobj(bufObj)) {
> @@ -299,7 +300,7 @@ print_draw_arrays(struct gl_context *ctx,
>               _mesa_vertex_attrib_address(array, binding);
>   
>            unsigned multiplier;
> -         switch (array->Type) {
> +         switch (array->Format.Type) {
>            case GL_DOUBLE:
>            case GL_INT64_ARB:
>            case GL_UNSIGNED_INT64_ARB:
> @@ -313,7 +314,7 @@ print_draw_arrays(struct gl_context *ctx,
>            int *k = (int *) f;
>            int i = 0;
>            int n = (count - 1) * (binding->Stride / (4 * multiplier))
> -           + array->Size;
> +            + array->Format.Size;
>            if (n > 32)
>               n = 32;
>            printf("  Data at offset %d:\n", offset);
> diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c
> index ac17539f09..ee77c45d03 100644
> --- a/src/mesa/main/get.c
> +++ b/src/mesa/main/get.c
> @@ -755,13 +755,22 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
>         v->value_bool = !!(ctx->Array.VAO->Enabled & VERT_BIT_POINT_SIZE);
>         break;
>   
> -   case GL_TEXTURE_COORD_ARRAY_SIZE:
>      case GL_TEXTURE_COORD_ARRAY_TYPE:
>      case GL_TEXTURE_COORD_ARRAY_STRIDE:
>         array = &ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)];
>         v->value_int = *(GLuint *) ((char *) array + d->offset);
>         break;
>   
> +   case GL_TEXTURE_COORD_ARRAY_SIZE:
> +      array = &ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)];
> +      v->value_int = array->Format.Size;
> +      break;
> +
> +   case GL_VERTEX_ARRAY_SIZE:
> +      array = &ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_POS];
> +      v->value_int = array->Format.Size;
> +      break;
> +
>      case GL_ACTIVE_TEXTURE_ARB:
>         v->value_int = GL_TEXTURE0_ARB + ctx->Texture.CurrentUnit;
>         break;
> @@ -969,11 +978,11 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
>      /* ARB_vertex_array_bgra */
>      case GL_COLOR_ARRAY_SIZE:
>         array = &ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_COLOR0];
> -      v->value_int = array->Format == GL_BGRA ? GL_BGRA : array->Size;
> +      v->value_int = array->Format.Format == GL_BGRA ? GL_BGRA : array->Format.Size;
>         break;
>      case GL_SECONDARY_COLOR_ARRAY_SIZE:
>         array = &ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_COLOR1];
> -      v->value_int = array->Format == GL_BGRA ? GL_BGRA : array->Size;
> +      v->value_int = array->Format.Format == GL_BGRA ? GL_BGRA : array->Format.Size;
>         break;
>   
>      /* ARB_copy_buffer */
> diff --git a/src/mesa/main/get_hash_params.py b/src/mesa/main/get_hash_params.py
> index ec5eef5f19..0b8ec9ea0b 100644
> --- a/src/mesa/main/get_hash_params.py
> +++ b/src/mesa/main/get_hash_params.py
> @@ -212,19 +212,19 @@ descriptor=[
>     [ "TEXTURE_MATRIX", "LOC_CUSTOM, TYPE_MATRIX, 0, extra_valid_texture_unit" ],
>     [ "TEXTURE_STACK_DEPTH", "LOC_CUSTOM, TYPE_INT, 0, extra_valid_texture_unit" ],
>     [ "VERTEX_ARRAY", "LOC_CUSTOM, TYPE_BOOLEAN, 0, NO_EXTRA" ],
> -  [ "VERTEX_ARRAY_SIZE", "ARRAY_UBYTE(VertexAttrib[VERT_ATTRIB_POS].Size), NO_EXTRA" ],
> -  [ "VERTEX_ARRAY_TYPE", "ARRAY_ENUM16(VertexAttrib[VERT_ATTRIB_POS].Type), NO_EXTRA" ],
> +  [ "VERTEX_ARRAY_SIZE", "LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA" ],
> +  [ "VERTEX_ARRAY_TYPE", "ARRAY_ENUM16(VertexAttrib[VERT_ATTRIB_POS].Format.Type), NO_EXTRA" ],
>     [ "VERTEX_ARRAY_STRIDE", "ARRAY_SHORT(VertexAttrib[VERT_ATTRIB_POS].Stride), NO_EXTRA" ],
>     [ "NORMAL_ARRAY", "LOC_CUSTOM, TYPE_BOOLEAN, 0, NO_EXTRA" ],
> -  [ "NORMAL_ARRAY_TYPE", "ARRAY_ENUM16(VertexAttrib[VERT_ATTRIB_NORMAL].Type), NO_EXTRA" ],
> +  [ "NORMAL_ARRAY_TYPE", "ARRAY_ENUM16(VertexAttrib[VERT_ATTRIB_NORMAL].Format.Type), NO_EXTRA" ],
>     [ "NORMAL_ARRAY_STRIDE", "ARRAY_SHORT(VertexAttrib[VERT_ATTRIB_NORMAL].Stride), NO_EXTRA" ],
>     [ "COLOR_ARRAY", "LOC_CUSTOM, TYPE_BOOLEAN, 0, NO_EXTRA" ],
>     [ "COLOR_ARRAY_SIZE", "LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA" ],
> -  [ "COLOR_ARRAY_TYPE", "ARRAY_ENUM16(VertexAttrib[VERT_ATTRIB_COLOR0].Type), NO_EXTRA" ],
> +  [ "COLOR_ARRAY_TYPE", "ARRAY_ENUM16(VertexAttrib[VERT_ATTRIB_COLOR0].Format.Type), NO_EXTRA" ],
>     [ "COLOR_ARRAY_STRIDE", "ARRAY_SHORT(VertexAttrib[VERT_ATTRIB_COLOR0].Stride), NO_EXTRA" ],
>     [ "TEXTURE_COORD_ARRAY", "LOC_CUSTOM, TYPE_BOOLEAN, 0, NO_EXTRA" ],
> -  [ "TEXTURE_COORD_ARRAY_SIZE", "LOC_CUSTOM, TYPE_UBYTE, offsetof(struct gl_array_attributes, Size), NO_EXTRA" ],
> -  [ "TEXTURE_COORD_ARRAY_TYPE", "LOC_CUSTOM, TYPE_ENUM16, offsetof(struct gl_array_attributes, Type), NO_EXTRA" ],
> +  [ "TEXTURE_COORD_ARRAY_SIZE", "LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA" ],
> +  [ "TEXTURE_COORD_ARRAY_TYPE", "LOC_CUSTOM, TYPE_ENUM16, offsetof(struct gl_array_attributes, Format.Type), NO_EXTRA" ],
>     [ "TEXTURE_COORD_ARRAY_STRIDE", "LOC_CUSTOM, TYPE_SHORT, offsetof(struct gl_array_attributes, Stride), NO_EXTRA" ],
>   
>   # GL_ARB_multitexture
> @@ -254,7 +254,7 @@ descriptor=[
>   { "apis": ["GLES"], "params": [
>   # OES_point_size_array
>     [ "POINT_SIZE_ARRAY_OES", "LOC_CUSTOM, TYPE_BOOLEAN, 0, NO_EXTRA" ],
> -  [ "POINT_SIZE_ARRAY_TYPE_OES", "ARRAY_FIELD(VertexAttrib[VERT_ATTRIB_POINT_SIZE].Type, TYPE_ENUM16), NO_EXTRA" ],
> +  [ "POINT_SIZE_ARRAY_TYPE_OES", "ARRAY_FIELD(VertexAttrib[VERT_ATTRIB_POINT_SIZE].Format.Type, TYPE_ENUM16), NO_EXTRA" ],
>     [ "POINT_SIZE_ARRAY_STRIDE_OES", "ARRAY_FIELD(VertexAttrib[VERT_ATTRIB_POINT_SIZE].Stride, TYPE_SHORT), NO_EXTRA" ],
>     [ "POINT_SIZE_ARRAY_BUFFER_BINDING_OES", "LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA" ],
>   ]},
> @@ -794,7 +794,7 @@ descriptor=[
>     [ "NORMAL_ARRAY_COUNT_EXT", "CONST(0), NO_EXTRA" ],
>     [ "COLOR_ARRAY_COUNT_EXT", "CONST(0), NO_EXTRA" ],
>     [ "INDEX_ARRAY", "LOC_CUSTOM, TYPE_BOOLEAN, 0, NO_EXTRA" ],
> -  [ "INDEX_ARRAY_TYPE", "ARRAY_ENUM16(VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Type), NO_EXTRA" ],
> +  [ "INDEX_ARRAY_TYPE", "ARRAY_ENUM16(VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Format.Type), NO_EXTRA" ],
>     [ "INDEX_ARRAY_STRIDE", "ARRAY_SHORT(VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Stride), NO_EXTRA" ],
>     [ "INDEX_ARRAY_COUNT_EXT", "CONST(0), NO_EXTRA" ],
>     [ "TEXTURE_COORD_ARRAY_COUNT_EXT", "CONST(0), NO_EXTRA" ],
> @@ -828,14 +828,14 @@ descriptor=[
>     [ "COLOR_SUM", "CONTEXT_BOOL(Fog.ColorSumEnabled), NO_EXTRA" ],
>     [ "CURRENT_SECONDARY_COLOR", "CONTEXT_FIELD(Current.Attrib[VERT_ATTRIB_COLOR1][0], TYPE_FLOATN_4), extra_flush_current" ],
>     [ "SECONDARY_COLOR_ARRAY", "LOC_CUSTOM, TYPE_BOOLEAN, 0, NO_EXTRA" ],
> -  [ "SECONDARY_COLOR_ARRAY_TYPE", "ARRAY_ENUM16(VertexAttrib[VERT_ATTRIB_COLOR1].Type), NO_EXTRA" ],
> +  [ "SECONDARY_COLOR_ARRAY_TYPE", "ARRAY_ENUM16(VertexAttrib[VERT_ATTRIB_COLOR1].Format.Type), NO_EXTRA" ],
>     [ "SECONDARY_COLOR_ARRAY_STRIDE", "ARRAY_SHORT(VertexAttrib[VERT_ATTRIB_COLOR1].Stride), NO_EXTRA" ],
>     [ "SECONDARY_COLOR_ARRAY_SIZE", "LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA" ],
>   
>   # GL_EXT_fog_coord
>     [ "CURRENT_FOG_COORDINATE", "CONTEXT_FLOAT(Current.Attrib[VERT_ATTRIB_FOG][0]), extra_flush_current" ],
>     [ "FOG_COORDINATE_ARRAY", "LOC_CUSTOM, TYPE_BOOLEAN, 0, NO_EXTRA" ],
> -  [ "FOG_COORDINATE_ARRAY_TYPE", "ARRAY_ENUM16(VertexAttrib[VERT_ATTRIB_FOG].Type), NO_EXTRA" ],
> +  [ "FOG_COORDINATE_ARRAY_TYPE", "ARRAY_ENUM16(VertexAttrib[VERT_ATTRIB_FOG].Format.Type), NO_EXTRA" ],
>     [ "FOG_COORDINATE_ARRAY_STRIDE", "ARRAY_SHORT(VertexAttrib[VERT_ATTRIB_FOG].Stride), NO_EXTRA" ],
>     [ "FOG_COORDINATE_SOURCE", "CONTEXT_ENUM16(Fog.FogCoordinateSource), NO_EXTRA" ],
>   
> diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
> index da6a261688..421b078337 100644
> --- a/src/mesa/main/mtypes.h
> +++ b/src/mesa/main/mtypes.h
> @@ -456,6 +456,21 @@ struct gl_colorbuffer_attrib
>   };
>   
>   
> +/**
> + * Vertex format to describe a vertex element.
> + */
> +struct gl_vertex_format
> +{
> +   GLenum16 Type;              /**< datatype: GL_FLOAT, GL_INT, etc */
> +   GLenum16 Format;            /**< default: GL_RGBA, but may be GL_BGRA */
> +   GLubyte Size:5;             /**< components per element (1,2,3,4) */
> +   unsigned char Normalized:1; /**< GL_ARB_vertex_program */
> +   unsigned char Integer:1;    /**< Integer-valued? */
> +   unsigned char Doubles:1;    /**< double values are not converted to floats */
> +   unsigned char _ElementSize; /**< Size of each element in bytes */

GLubyte ?


> +};
> +
> +
>   /**
>    * Current attribute group (GL_CURRENT_BIT).
>    */
> @@ -1419,14 +1434,10 @@ struct gl_array_attributes
>      const GLubyte *Ptr;
>      /** Offset of the first element relative to the binding offset */
>      GLuint RelativeOffset;
> -   GLshort Stride;          /**< Stride as specified with gl*Pointer() */
> -   GLenum16 Type;           /**< Datatype: GL_FLOAT, GL_INT, etc */
> -   GLenum16 Format;         /**< Default: GL_RGBA, but may be GL_BGRA */
> -   GLubyte Size;            /**< Components per element (1,2,3,4) */
> -   unsigned Normalized:1;   /**< Fixed-point values are normalized when converted to floats */
> -   unsigned Integer:1;      /**< Fixed-point values are not converted to floats */
> -   unsigned Doubles:1;      /**< double precision values are not converted to floats */
> -   unsigned _ElementSize:8; /**< Size of each element in bytes */
> +   /** Vertex format */
> +   struct gl_vertex_format Format;
> +   /** Stride as specified with gl*Pointer() */
> +   GLshort Stride;
>      /** Index into gl_vertex_array_object::BufferBinding[] array */
>      unsigned BufferBindingIndex:6;
>   
> diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c
> index a6d00c6ef9..2507e5338c 100644
> --- a/src/mesa/main/varray.c
> +++ b/src/mesa/main/varray.c
> @@ -33,6 +33,7 @@
>   #include "context.h"
>   #include "enable.h"
>   #include "enums.h"
> +#include "glformats.h"
>   #include "hash.h"
>   #include "image.h"
>   #include "macros.h"
> @@ -243,6 +244,24 @@ vertex_binding_divisor(struct gl_context *ctx,
>   }
>   
>   
> +void
> +_mesa_set_vertex_format(struct gl_vertex_format *vertex_format,
> +                        GLubyte size, GLenum16 type, GLenum16 format,
> +                        GLboolean normalized, GLboolean integer,
> +                        GLboolean doubles)
> +{
> +   assert(size <= 4);
> +   vertex_format->Type = type;
> +   vertex_format->Format = format;
> +   vertex_format->Size = size;
> +   vertex_format->Normalized = normalized;
> +   vertex_format->Integer = integer;
> +   vertex_format->Doubles = doubles;
> +   vertex_format->_ElementSize = _mesa_bytes_per_vertex_attrib(size, type);
> +   assert(vertex_format->_ElementSize <= 4*sizeof(double));
> +}
> +
> +
>   /**
>    * Examine the API profile and extensions to determine which types are legal
>    * for vertex arrays.  This is called once from update_array_format().
> @@ -330,22 +349,13 @@ _mesa_update_array_format(struct gl_context *ctx,
>                             GLuint relativeOffset)
>   {
>      struct gl_array_attributes *const array = &vao->VertexAttrib[attrib];
> -   GLint elementSize;
>   
>      assert(!vao->SharedAndImmutable);
>      assert(size <= 4);
>   
> -   elementSize = _mesa_bytes_per_vertex_attrib(size, type);
> -   assert(elementSize != -1);
> -
> -   array->Size = size;
> -   array->Type = type;
> -   array->Format = format;
> -   array->Normalized = normalized;
> -   array->Integer = integer;
> -   array->Doubles = doubles;
>      array->RelativeOffset = relativeOffset;
> -   array->_ElementSize = elementSize;
> +   _mesa_set_vertex_format(&array->Format, size, type, format,
> +                           normalized, integer, doubles);
>   
>      vao->NewArrays |= vao->Enabled & VERT_BIT(attrib);
>      if (vao == ctx->Array.VAO)
> @@ -609,7 +619,8 @@ update_array(struct gl_context *ctx,
>      array->Ptr = ptr;
>   
>      /* Update the vertex buffer binding */
> -   GLsizei effectiveStride = stride != 0 ? stride : array->_ElementSize;
> +   GLsizei effectiveStride = stride != 0 ?
> +      stride : array->Format._ElementSize;
>      _mesa_bind_vertex_buffer(ctx, vao, attrib,
>                               ctx->Array.ArrayBufferObj, (GLintptr) ptr,
>                               effectiveStride);
> @@ -1269,25 +1280,25 @@ get_vertex_array_attrib(struct gl_context *ctx,
>      case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
>         return !!(vao->Enabled & VERT_BIT_GENERIC(index));
>      case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
> -      return (array->Format == GL_BGRA) ? GL_BGRA : array->Size;
> +      return (array->Format.Format == GL_BGRA) ? GL_BGRA : array->Format.Size;
>      case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
>         return array->Stride;
>      case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
> -      return array->Type;
> +      return array->Format.Type;
>      case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
> -      return array->Normalized;
> +      return array->Format.Normalized;
>      case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
>         return vao->BufferBinding[array->BufferBindingIndex].BufferObj->Name;
>      case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
>         if ((_mesa_is_desktop_gl(ctx)
>              && (ctx->Version >= 30 || ctx->Extensions.EXT_gpu_shader4))
>             || _mesa_is_gles3(ctx)) {
> -         return array->Integer;
> +         return array->Format.Integer;
>         }
>         goto error;
>      case GL_VERTEX_ATTRIB_ARRAY_LONG:
>         if (_mesa_is_desktop_gl(ctx)) {
> -         return array->Doubles;
> +         return array->Format.Doubles;
>         }
>         goto error;
>      case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB:
> @@ -2771,17 +2782,11 @@ _mesa_copy_vertex_attrib_array(struct gl_context *ctx,
>                                  struct gl_array_attributes *dst,
>                                  const struct gl_array_attributes *src)
>   {
> -   dst->Size           = src->Size;
> -   dst->Type           = src->Type;
> -   dst->Format         = src->Format;
> -   dst->BufferBindingIndex = src->BufferBindingIndex;
> -   dst->RelativeOffset = src->RelativeOffset;
> -   dst->Format         = src->Format;
> -   dst->Integer        = src->Integer;
> -   dst->Doubles        = src->Doubles;
> -   dst->Normalized     = src->Normalized;
>      dst->Ptr            = src->Ptr;
> -   dst->_ElementSize   = src->_ElementSize;
> +   dst->RelativeOffset = src->RelativeOffset;
> +   _mesa_copy_vertex_format(&dst->Format, &src->Format);
> +   dst->Stride         = src->Stride;
> +   dst->BufferBindingIndex = src->BufferBindingIndex;
>      dst->_EffBufferBindingIndex = src->_EffBufferBindingIndex;
>      dst->_EffRelativeOffset = src->_EffRelativeOffset;
>   }
> @@ -2823,8 +2828,9 @@ _mesa_print_arrays(struct gl_context *ctx)
>         fprintf(stderr, "  %s: Ptr=%p, Type=%s, Size=%d, ElemSize=%u, "
>                 "Stride=%d, Buffer=%u(Size %lu)\n",
>                 gl_vert_attrib_name((gl_vert_attrib)i),
> -              array->Ptr, _mesa_enum_to_string(array->Type), array->Size,
> -              array->_ElementSize, binding->Stride, bo->Name,
> +              array->Ptr, _mesa_enum_to_string(array->Format.Type),
> +              array->Format.Size,
> +              array->Format._ElementSize, binding->Stride, bo->Name,
>                 (unsigned long) bo->Size);
>      }
>   }
> diff --git a/src/mesa/main/varray.h b/src/mesa/main/varray.h
> index 823e4f408b..fcb688f89f 100644
> --- a/src/mesa/main/varray.h
> +++ b/src/mesa/main/varray.h
> @@ -29,6 +29,26 @@
>   
>   #include "bufferobj.h"
>   
> +void
> +_mesa_set_vertex_format(struct gl_vertex_format *vertex_format,
> +                        GLubyte size, GLenum16 type, GLenum16 format,
> +                        GLboolean normalized, GLboolean integer,
> +                        GLboolean doubles);
> +
> +
> +static inline void
> +_mesa_copy_vertex_format(struct gl_vertex_format *dst,
> +                         const struct gl_vertex_format *src)
> +{
> +   dst->Type = src->Type;
> +   dst->Format = src->Format;
> +   dst->Size = src->Size;
> +   dst->Normalized = src->Normalized;
> +   dst->Integer = src->Integer;
> +   dst->Doubles = src->Doubles;
> +   dst->_ElementSize = src->_ElementSize;
> +}

Do we really need this function?  Can't we just use ordinary assignments?


> +
>   
>   /**
>    * Returns a pointer to the vertex attribute data in a client array,
> diff --git a/src/mesa/state_tracker/st_atom.h b/src/mesa/state_tracker/st_atom.h
> index 96e128d38c..9f3ca38c19 100644
> --- a/src/mesa/state_tracker/st_atom.h
> +++ b/src/mesa/state_tracker/st_atom.h
> @@ -55,7 +55,7 @@ void st_validate_state( struct st_context *st, enum st_pipeline pipeline );
>   GLuint st_compare_func_to_pipe(GLenum func);
>   
>   enum pipe_format
> -st_pipe_vertex_format(const struct gl_array_attributes *attrib);
> +st_pipe_vertex_format(const struct gl_vertex_format *glformat);
>   
>   
>   /* Define ST_NEW_xxx_INDEX */
> diff --git a/src/mesa/state_tracker/st_atom_array.c b/src/mesa/state_tracker/st_atom_array.c
> index e4fc19eb5e..19a5ef29a9 100644
> --- a/src/mesa/state_tracker/st_atom_array.c
> +++ b/src/mesa/state_tracker/st_atom_array.c
> @@ -238,18 +238,18 @@ static const uint16_t vertex_formats[][4][4] = {
>    * Return a PIPE_FORMAT_x for the given GL datatype and size.
>    */
>   enum pipe_format
> -st_pipe_vertex_format(const struct gl_array_attributes *attrib)
> +st_pipe_vertex_format(const struct gl_vertex_format *vformat)
>   {
> -   const GLubyte size = attrib->Size;
> -   const GLenum16 format = attrib->Format;
> -   const bool normalized = attrib->Normalized;
> -   const bool integer = attrib->Integer;
> -   GLenum16 type = attrib->Type;
> +   const GLubyte size = vformat->Size;
> +   const GLenum16 format = vformat->Format;
> +   const bool normalized = vformat->Normalized;
> +   const bool integer = vformat->Integer;
> +   GLenum16 type = vformat->Type;
>      unsigned index;
>   
>      assert(size >= 1 && size <= 4);
>      assert(format == GL_RGBA || format == GL_BGRA);
> -   assert(attrib->_ElementSize == _mesa_bytes_per_vertex_attrib(size, type));
> +   assert(vformat->_ElementSize == _mesa_bytes_per_vertex_attrib(size, type));
>   
>      switch (type) {
>      case GL_HALF_FLOAT_OES:
> @@ -320,13 +320,13 @@ static void init_velement(struct pipe_vertex_element *velement,
>   
>   static void init_velement_lowered(const struct st_vertex_program *vp,
>                                     struct pipe_vertex_element *velements,
> -                                  const struct gl_array_attributes *attrib,
> +                                  const struct gl_vertex_format *vformat,
>                                     int src_offset, int instance_divisor,
>                                     int vbo_index, int idx)
>   {
> -   const GLubyte nr_components = attrib->Size;
> +   const GLubyte nr_components = vformat->Size;
>   
> -   if (attrib->Doubles) {
> +   if (vformat->Doubles) {
>         int lower_format;
>   
>         if (nr_components < 2)
> @@ -357,7 +357,7 @@ static void init_velement_lowered(const struct st_vertex_program *vp,
>            }
>         }
>      } else {
> -      const unsigned format = st_pipe_vertex_format(attrib);
> +      const unsigned format = st_pipe_vertex_format(vformat);
>   
>         init_velement(&velements[idx], src_offset,
>                       format, instance_divisor, vbo_index);
> @@ -447,7 +447,7 @@ st_update_array(struct st_context *st)
>            const struct gl_array_attributes *const attrib
>               = _mesa_draw_array_attrib(vao, attr);
>            const GLuint off = _mesa_draw_attributes_relative_offset(attrib);
> -         init_velement_lowered(vp, velements, attrib, off,
> +         init_velement_lowered(vp, velements, &attrib->Format, off,
>                                  binding->InstanceDivisor, bufidx,
>                                  input_to_index[attr]);
>         }
> @@ -468,14 +468,14 @@ st_update_array(struct st_context *st)
>            const gl_vert_attrib attr = u_bit_scan(&curmask);
>            const struct gl_array_attributes *const attrib
>               = _mesa_draw_current_attrib(ctx, attr);
> -         const unsigned size = attrib->_ElementSize;
> +         const unsigned size = attrib->Format._ElementSize;
>            const unsigned alignment = util_next_power_of_two(size);
>            max_alignment = MAX2(max_alignment, alignment);
>            memcpy(cursor, attrib->Ptr, size);
>            if (alignment != size)
>               memset(cursor + size, 0, alignment - size);
>   
> -         init_velement_lowered(vp, velements, attrib, cursor - data, 0,
> +         init_velement_lowered(vp, velements, &attrib->Format, cursor - data, 0,
>                                  bufidx, input_to_index[attr]);
>   
>            cursor += alignment;
> diff --git a/src/mesa/state_tracker/st_draw_feedback.c b/src/mesa/state_tracker/st_draw_feedback.c
> index eb05ac9669..11097b4cac 100644
> --- a/src/mesa/state_tracker/st_draw_feedback.c
> +++ b/src/mesa/state_tracker/st_draw_feedback.c
> @@ -212,7 +212,7 @@ st_feedback_draw_vbo(struct gl_context *ctx,
>         vbuffers[attr].stride = binding->Stride; /* in bytes */
>         velements[attr].instance_divisor = 0;
>         velements[attr].vertex_buffer_index = attr;
> -      velements[attr].src_format = st_pipe_vertex_format(attrib);
> +      velements[attr].src_format = st_pipe_vertex_format(&attrib->Format);
>         assert(velements[attr].src_format);
>   
>         /* tell draw about this attribute */
> diff --git a/src/mesa/tnl/t_draw.c b/src/mesa/tnl/t_draw.c
> index 1fe2d405cb..009a0bf362 100644
> --- a/src/mesa/tnl/t_draw.c
> +++ b/src/mesa/tnl/t_draw.c
> @@ -70,7 +70,7 @@ static void free_space(struct gl_context *ctx)
>    */
>   #define CONVERT( TYPE, MACRO ) do {		\
>      GLuint i, j;					\
> -   if (attrib->Normalized) {			\
> +   if (attrib->Format.Normalized) {		\
>         for (i = 0; i < count; i++) {		\
>   	 const TYPE *in = (TYPE *)ptr;		\
>   	 for (j = 0; j < sz; j++) {		\
> @@ -104,8 +104,8 @@ convert_bgra_to_float(const struct gl_vertex_buffer_binding *binding,
>                         GLuint count )
>   {
>      GLuint i;
> -   assert(attrib->Normalized);
> -   assert(attrib->Size == 4);
> +   assert(attrib->Format.Normalized);
> +   assert(attrib->Format.Size == 4);
>      for (i = 0; i < count; i++) {
>         const GLubyte *in = (GLubyte *) ptr;  /* in is in BGRA order */
>         *fptr++ = UBYTE_TO_FLOAT(in[2]);  /* red */
> @@ -152,9 +152,9 @@ convert_fixed_to_float(const struct gl_vertex_buffer_binding *binding,
>   {
>      GLuint i;
>      GLint j;
> -   const GLint size = attrib->Size;
> +   const GLint size = attrib->Format.Size;
>   
> -   if (attrib->Normalized) {
> +   if (attrib->Format.Normalized) {
>         for (i = 0; i < count; ++i) {
>            const GLfixed *in = (GLfixed *) ptr;
>            for (j = 0; j < size; ++j) {
> @@ -187,17 +187,17 @@ static void _tnl_import_array( struct gl_context *ctx,
>      struct vertex_buffer *VB = &tnl->vb;
>      GLuint stride = binding->Stride;
>   
> -   if (attrib->Type != GL_FLOAT) {
> -      const GLuint sz = attrib->Size;
> +   if (attrib->Format.Type != GL_FLOAT) {
> +      const GLuint sz = attrib->Format.Size;
>         GLubyte *buf = get_space(ctx, count * sz * sizeof(GLfloat));
>         GLfloat *fptr = (GLfloat *)buf;
>   
> -      switch (attrib->Type) {
> +      switch (attrib->Format.Type) {
>         case GL_BYTE:
>   	 CONVERT(GLbyte, BYTE_TO_FLOAT);
>   	 break;
>         case GL_UNSIGNED_BYTE:
> -         if (attrib->Format == GL_BGRA) {
> +         if (attrib->Format.Format == GL_BGRA) {
>               /* See GL_EXT_vertex_array_bgra */
>               convert_bgra_to_float(binding, attrib, ptr, fptr, count);
>            }
> @@ -240,11 +240,11 @@ static void _tnl_import_array( struct gl_context *ctx,
>      VB->AttribPtr[attr]->start = (GLfloat *)ptr;
>      VB->AttribPtr[attr]->count = count;
>      VB->AttribPtr[attr]->stride = stride;
> -   VB->AttribPtr[attr]->size = attrib->Size;
> +   VB->AttribPtr[attr]->size = attrib->Format.Size;
>   
>      /* This should die, but so should the whole GLvector4f concept:
>       */
> -   VB->AttribPtr[attr]->flags = (((1<<attrib->Size)-1) |
> +   VB->AttribPtr[attr]->flags = (((1<<attrib->Format.Size)-1) |
>   				   VEC_NOT_WRITEABLE |
>   				   (stride == 4*sizeof(GLfloat) ? 0 : VEC_BAD_STRIDE));
>      
> diff --git a/src/mesa/tnl/t_split_copy.c b/src/mesa/tnl/t_split_copy.c
> index 1732b4c9ca..e04cfad049 100644
> --- a/src/mesa/tnl/t_split_copy.c
> +++ b/src/mesa/tnl/t_split_copy.c
> @@ -169,7 +169,7 @@ dump_draw_info(struct gl_context *ctx,
>            const GLubyte *ptr = _mesa_vertex_attrib_address(attrib, binding);
>            printf("    array %d at %p:\n", j, (void*) &arrays[j]);
>            printf("      ptr %p, size %d, type 0x%x, stride %d\n",
> -                ptr, attrib->Size, attrib->Type, binding->Stride);
> +                ptr, attrib->Format.Size, attrib->Format.Type, binding->Stride);
>            if (0) {
>               GLint k = prims[i].start + prims[i].count - 1;
>               GLfloat *last = (GLfloat *) (ptr + binding->Stride * k);
> @@ -269,7 +269,7 @@ elt(struct copy_context *copy, GLuint elt_idx)
>            csr += copy->varying[i].size;
>   
>   #ifdef NAN_CHECK
> -         if (srcarray->Type == GL_FLOAT) {
> +         if (srcarray->Format.Type == GL_FLOAT) {
>               GLuint k;
>               GLfloat *f = (GLfloat *) srcptr;
>               for (k = 0; k < srcarray->Size; k++) {
> @@ -451,8 +451,8 @@ replay_init(struct copy_context *copy)
>   
>            copy->varying[j].attr = i;
>            copy->varying[j].array = &copy->array[i];
> -         copy->varying[j].size = attrib->_ElementSize;
> -         copy->vertex_size += attrib->_ElementSize;
> +         copy->varying[j].size = attrib->Format._ElementSize;
> +         copy->vertex_size += attrib->Format._ElementSize;
>   
>            if (_mesa_is_bufferobj(vbo) &&
>                !_mesa_bufferobj_mapped(vbo, MAP_INTERNAL))
> @@ -528,16 +528,10 @@ replay_init(struct copy_context *copy)
>         struct gl_vertex_buffer_binding *dstbind = &copy->varying[i].dstbinding;
>         struct gl_array_attributes *dstattr = &copy->varying[i].dstattribs;
>   
> -      dstattr->Size = srcattr->Size;
> -      dstattr->Type = srcattr->Type;
> -      dstattr->Format = GL_RGBA;
> -      dstbind->Stride = copy->vertex_size;
> +      _mesa_copy_vertex_format(&dstattr->Format, &srcattr->Format);

Can't we just do dstattr->Format = srcattr->Format?


>         dstattr->Ptr = copy->dstbuf + offset;
> -      dstattr->Normalized = srcattr->Normalized;
> -      dstattr->Integer = srcattr->Integer;
> -      dstattr->Doubles = srcattr->Doubles;
> +      dstbind->Stride = copy->vertex_size;
>         dstbind->BufferObj = ctx->Shared->NullBufferObj;
> -      dstattr->_ElementSize = srcattr->_ElementSize;
>         dst->BufferBinding = dstbind;
>         dst->VertexAttrib = dstattr;
>   
> diff --git a/src/mesa/vbo/vbo_context.c b/src/mesa/vbo/vbo_context.c
> index 364de2c507..484625d9ac 100644
> --- a/src/mesa/vbo/vbo_context.c
> +++ b/src/mesa/vbo/vbo_context.c
> @@ -58,11 +58,8 @@ init_array(struct gl_context *ctx, struct gl_array_attributes *attrib,
>   {
>      memset(attrib, 0, sizeof(*attrib));
>   
> -   attrib->Size = size;
> -   attrib->Type = GL_FLOAT;
> -   attrib->Format = GL_RGBA;
> +   vbo_set_vertex_format(&attrib->Format, size, GL_FLOAT);
>      attrib->Stride = 0;
> -   attrib->_ElementSize = size * sizeof(GLfloat);
>      attrib->Ptr = pointer;
>   }
>   
> diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c
> index 24bd1f0ba1..fd88b7d2d4 100644
> --- a/src/mesa/vbo/vbo_exec_api.c
> +++ b/src/mesa/vbo/vbo_exec_api.c
> @@ -195,7 +195,7 @@ vbo_exec_copy_to_current(struct vbo_exec_context *exec)
>                                        exec->vtx.attrtype[i]);
>         }
>   
> -      if (exec->vtx.attrtype[i] != vbo->current[i].Type ||
> +      if (exec->vtx.attrtype[i] != vbo->current[i].Format.Type ||
>             memcmp(current, tmp, 4 * sizeof(GLfloat) * dmul) != 0) {
>            memcpy(current, tmp, 4 * sizeof(GLfloat) * dmul);
>   
> @@ -205,14 +205,9 @@ vbo_exec_copy_to_current(struct vbo_exec_context *exec)
>             * directly.
>             */
>            /* Size here is in components - not bytes */
> -         vbo->current[i].Size = exec->vtx.attrsz[i] / dmul;
> -         vbo->current[i]._ElementSize =
> -            vbo->current[i].Size * sizeof(GLfloat) * dmul;
> -         vbo->current[i].Type = exec->vtx.attrtype[i];
> -         vbo->current[i].Integer =
> -            vbo_attrtype_to_integer_flag(exec->vtx.attrtype[i]);
> -         vbo->current[i].Doubles =
> -            vbo_attrtype_to_double_flag(exec->vtx.attrtype[i]);
> +         vbo_set_vertex_format(&vbo->current[i].Format,
> +                               exec->vtx.attrsz[i] / dmul,
> +                               exec->vtx.attrtype[i]);
>   
>            /* This triggers rather too much recalculation of Mesa state
>             * that doesn't get used (eg light positions).
> diff --git a/src/mesa/vbo/vbo_private.h b/src/mesa/vbo/vbo_private.h
> index 1fc2ab48fd..6110a6cc0e 100644
> --- a/src/mesa/vbo/vbo_private.h
> +++ b/src/mesa/vbo/vbo_private.h
> @@ -115,6 +115,16 @@ vbo_attrtype_to_double_flag(GLenum format)
>   }
>   
>   
> +static inline void
> +vbo_set_vertex_format(struct gl_vertex_format* vertex_format,
> +                      GLubyte size, GLenum16 type)
> +{
> +   _mesa_set_vertex_format(vertex_format, size, type, GL_RGBA, GL_FALSE,
> +                           vbo_attrtype_to_integer_flag(type),
> +                           vbo_attrtype_to_double_flag(type));
> +}
> +
> +
>   /**
>    * Return default component values for the given format.
>    * The return type is an array of fi_types, because that's how we declare
> diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c
> index 8dc03b9f77..fb8d68d556 100644
> --- a/src/mesa/vbo/vbo_save_api.c
> +++ b/src/mesa/vbo/vbo_save_api.c
> @@ -450,14 +450,14 @@ compare_vao(gl_vertex_processing_mode mode,
>         const struct gl_array_attributes *attrib = &vao->VertexAttrib[attr];
>         if (attrib->RelativeOffset + vao->BufferBinding[0].Offset != off)
>            return false;
> -      if (attrib->Type != tp)
> +      if (attrib->Format.Type != tp)
>            return false;
> -      if (attrib->Size != size[vbo_attr])
> +      if (attrib->Format.Size != size[vbo_attr])
>            return false;
> -      assert(attrib->Format == GL_RGBA);
> -      assert(attrib->Normalized == GL_FALSE);
> -      assert(attrib->Integer == vbo_attrtype_to_integer_flag(tp));
> -      assert(attrib->Doubles == vbo_attrtype_to_double_flag(tp));
> +      assert(attrib->Format.Format == GL_RGBA);
> +      assert(attrib->Format.Normalized == GL_FALSE);
> +      assert(attrib->Format.Integer == vbo_attrtype_to_integer_flag(tp));
> +      assert(attrib->Format.Doubles == vbo_attrtype_to_double_flag(tp));
>         assert(attrib->BufferBindingIndex == 0);
>      }
>   
> diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c
> index b3578cc27c..b5807bb377 100644
> --- a/src/mesa/vbo/vbo_save_draw.c
> +++ b/src/mesa/vbo/vbo_save_draw.c
> @@ -52,8 +52,8 @@ copy_vao(struct gl_context *ctx, const struct gl_vertex_array_object *vao,
>         const int i = u_bit_scan(&mask);
>         const struct gl_array_attributes *attrib = &vao->VertexAttrib[i];
>         struct gl_array_attributes *currval = &vbo->current[shift + i];
> -      const GLubyte size = attrib->Size;
> -      const GLenum16 type = attrib->Type;
> +      const GLubyte size = attrib->Format.Size;
> +      const GLenum16 type = attrib->Format.Type;
>         fi_type tmp[8];
>         int dmul = 1;
>   
> @@ -66,17 +66,11 @@ copy_vao(struct gl_context *ctx, const struct gl_vertex_array_object *vao,
>         else
>            COPY_CLEAN_4V_TYPE_AS_UNION(tmp, size, *data, type);
>   
> -      if (type != currval->Type ||
> +      if (type != currval->Format.Type ||
>             memcmp(currval->Ptr, tmp, 4 * sizeof(GLfloat) * dmul) != 0) {
>            memcpy((fi_type*)currval->Ptr, tmp, 4 * sizeof(GLfloat) * dmul);
>   
> -         currval->Size = size;
> -         currval->_ElementSize = size * sizeof(GLfloat) * dmul;
> -         currval->Type = type;
> -         currval->Integer = vbo_attrtype_to_integer_flag(type);
> -         currval->Doubles = vbo_attrtype_to_double_flag(type);
> -         currval->Normalized = GL_FALSE;
> -         currval->Format = GL_RGBA;
> +         vbo_set_vertex_format(&currval->Format, size, type);
>   
>            ctx->NewState |= state;
>         }
> diff --git a/src/mesa/vbo/vbo_save_loopback.c b/src/mesa/vbo/vbo_save_loopback.c
> index 7e9296bae2..26a9f94fac 100644
> --- a/src/mesa/vbo/vbo_save_loopback.c
> +++ b/src/mesa/vbo/vbo_save_loopback.c
> @@ -139,7 +139,7 @@ append_attr(GLuint *nr, struct loopback_attr la[], int i, int shift,
>   {
>      la[*nr].index = shift + i;
>      la[*nr].offset = vao->VertexAttrib[i].RelativeOffset;
> -   la[*nr].func = vert_attrfunc[vao->VertexAttrib[i].Size - 1];
> +   la[*nr].func = vert_attrfunc[vao->VertexAttrib[i].Format.Size - 1];
>      (*nr)++;
>   }
>   
> 



More information about the mesa-dev mailing list