From: Fredrik Höglund Date: Tue, 9 Apr 2013 18:54:25 +0000 (+0200) Subject: mesa: Add ARB_vertex_attrib_binding X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=59b01ca252bd6706f08cd80a864819d71dfe741c;p=mesa.git mesa: Add ARB_vertex_attrib_binding update_array() and update_array_format() are changed to update the new attrib and binding states, and the client arrays become derived state. Reviewed-by: Eric Anholt --- diff --git a/src/mesa/main/api_arrayelt.c b/src/mesa/main/api_arrayelt.c index 5a316f0c168..6822465e8b1 100644 --- a/src/mesa/main/api_arrayelt.c +++ b/src/mesa/main/api_arrayelt.c @@ -35,6 +35,7 @@ */ #include "glheader.h" +#include "arrayobj.h" #include "api_arrayelt.h" #include "bufferobj.h" #include "context.h" @@ -1485,6 +1486,12 @@ _ae_update_state(struct gl_context *ctx) actx->nr_vbos = 0; + if (arrayObj->NewArrays) { + /* update the derived client arrays */ + _mesa_update_array_object_client_arrays(ctx, arrayObj); + arrayObj->NewArrays = 0; + } + /* conventional vertex arrays */ if (arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled) { aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR_INDEX]; diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c index d31f5936147..f285c9748ed 100644 --- a/src/mesa/main/api_validate.c +++ b/src/mesa/main/api_validate.c @@ -120,7 +120,7 @@ check_valid_to_render(struct gl_context *ctx, const char *function) case API_OPENGLES: /* For OpenGL ES, only draw if we have vertex positions */ - if (!ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_POS].Enabled) + if (!ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled) return GL_FALSE; break; @@ -141,8 +141,8 @@ check_valid_to_render(struct gl_context *ctx, const char *function) /* Draw if we have vertex positions (GL_VERTEX_ARRAY or generic * array [0]). */ - return (ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_POS].Enabled || - ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC0].Enabled); + return (ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled || + ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC0].Enabled); } } break; diff --git a/src/mesa/main/arrayobj.c b/src/mesa/main/arrayobj.c index 79a54fa68be..dbf8fdc7315 100644 --- a/src/mesa/main/arrayobj.c +++ b/src/mesa/main/arrayobj.c @@ -72,7 +72,7 @@ _mesa_lookup_arrayobj(struct gl_context *ctx, GLuint id) /** - * For all the vertex arrays in the array object, unbind any pointers + * For all the vertex binding points in the array object, unbind any pointers * to any buffer objects (VBOs). * This is done just prior to array object destruction. */ @@ -81,6 +81,9 @@ unbind_array_object_vbos(struct gl_context *ctx, struct gl_array_object *obj) { GLuint i; + for (i = 0; i < Elements(obj->VertexBinding); i++) + _mesa_reference_buffer_object(ctx, &obj->VertexBinding[i].BufferObj, NULL); + for (i = 0; i < Elements(obj->_VertexAttrib); i++) _mesa_reference_buffer_object(ctx, &obj->_VertexAttrib[i].BufferObj, NULL); } @@ -181,20 +184,30 @@ _mesa_reference_array_object_(struct gl_context *ctx, static void init_array(struct gl_context *ctx, - struct gl_client_array *array, GLint size, GLint type) + struct gl_array_object *obj, GLuint index, GLint size, GLint type) { + struct gl_vertex_attrib_array *array = &obj->VertexAttrib[index]; + struct gl_vertex_buffer_binding *binding = &obj->VertexBinding[index]; + array->Size = size; array->Type = type; array->Format = GL_RGBA; /* only significant for GL_EXT_vertex_array_bgra */ array->Stride = 0; - array->StrideB = 0; array->Ptr = NULL; + array->RelativeOffset = 0; array->Enabled = GL_FALSE; array->Normalized = GL_FALSE; array->Integer = GL_FALSE; array->_ElementSize = size * _mesa_sizeof_type(type); + array->VertexBinding = index; + + binding->Offset = 0; + binding->Stride = array->_ElementSize; + binding->BufferObj = NULL; + binding->_BoundArrays = BITFIELD64_BIT(index); + /* Vertex array buffers */ - _mesa_reference_buffer_object(ctx, &array->BufferObj, + _mesa_reference_buffer_object(ctx, &binding->BufferObj, ctx->Shared->NullBufferObj); } @@ -218,28 +231,28 @@ _mesa_initialize_array_object( struct gl_context *ctx, for (i = 0; i < Elements(obj->_VertexAttrib); i++) { switch (i) { case VERT_ATTRIB_WEIGHT: - init_array(ctx, &obj->_VertexAttrib[VERT_ATTRIB_WEIGHT], 1, GL_FLOAT); + init_array(ctx, obj, VERT_ATTRIB_WEIGHT, 1, GL_FLOAT); break; case VERT_ATTRIB_NORMAL: - init_array(ctx, &obj->_VertexAttrib[VERT_ATTRIB_NORMAL], 3, GL_FLOAT); + init_array(ctx, obj, VERT_ATTRIB_NORMAL, 3, GL_FLOAT); break; case VERT_ATTRIB_COLOR1: - init_array(ctx, &obj->_VertexAttrib[VERT_ATTRIB_COLOR1], 3, GL_FLOAT); + init_array(ctx, obj, VERT_ATTRIB_COLOR1, 3, GL_FLOAT); break; case VERT_ATTRIB_FOG: - init_array(ctx, &obj->_VertexAttrib[VERT_ATTRIB_FOG], 1, GL_FLOAT); + init_array(ctx, obj, VERT_ATTRIB_FOG, 1, GL_FLOAT); break; case VERT_ATTRIB_COLOR_INDEX: - init_array(ctx, &obj->_VertexAttrib[VERT_ATTRIB_COLOR_INDEX], 1, GL_FLOAT); + init_array(ctx, obj, VERT_ATTRIB_COLOR_INDEX, 1, GL_FLOAT); break; case VERT_ATTRIB_EDGEFLAG: - init_array(ctx, &obj->_VertexAttrib[VERT_ATTRIB_EDGEFLAG], 1, GL_BOOL); + init_array(ctx, obj, VERT_ATTRIB_EDGEFLAG, 1, GL_BOOL); break; case VERT_ATTRIB_POINT_SIZE: - init_array(ctx, &obj->_VertexAttrib[VERT_ATTRIB_POINT_SIZE], 1, GL_FLOAT); + init_array(ctx, obj, VERT_ATTRIB_POINT_SIZE, 1, GL_FLOAT); break; default: - init_array(ctx, &obj->_VertexAttrib[i], 4, GL_FLOAT); + init_array(ctx, obj, i, 4, GL_FLOAT); break; } } @@ -322,6 +335,32 @@ _mesa_update_array_object_max_element(struct gl_context *ctx, } +/** + * Updates the derived gl_client_arrays when a gl_vertex_attrib_array + * or a gl_vertex_buffer_binding has changed. + */ +void +_mesa_update_array_object_client_arrays(struct gl_context *ctx, struct gl_array_object *arrayObj) +{ + GLbitfield64 arrays = arrayObj->NewArrays; + + while (arrays) { + struct gl_client_array *client_array; + struct gl_vertex_attrib_array *attrib_array; + struct gl_vertex_buffer_binding *buffer_binding; + + GLint attrib = ffsll(arrays) - 1; + arrays ^= BITFIELD64_BIT(attrib); + + attrib_array = &arrayObj->VertexAttrib[attrib]; + buffer_binding = &arrayObj->VertexBinding[attrib_array->VertexBinding]; + client_array = &arrayObj->_VertexAttrib[attrib]; + + _mesa_update_client_array(ctx, client_array, attrib_array, buffer_binding); + } +} + + /**********************************************************************/ /* API Functions */ /**********************************************************************/ diff --git a/src/mesa/main/arrayobj.h b/src/mesa/main/arrayobj.h index 492ef350161..7c3720242b0 100644 --- a/src/mesa/main/arrayobj.h +++ b/src/mesa/main/arrayobj.h @@ -78,6 +78,11 @@ extern void _mesa_update_array_object_max_element(struct gl_context *ctx, struct gl_array_object *arrayObj); +extern void +_mesa_update_array_object_client_arrays(struct gl_context *ctx, + struct gl_array_object *arrayObj); + + /** Returns the bitmask of all enabled arrays in fixed function mode. * * In fixed function mode only the traditional fixed function arrays diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c index 87c7f66eb11..c9332bd522d 100644 --- a/src/mesa/main/attrib.c +++ b/src/mesa/main/attrib.c @@ -1369,8 +1369,11 @@ copy_array_object(struct gl_context *ctx, /* In theory must be the same anyway, but on recreate make sure it matches */ dest->ARBsemantics = src->ARBsemantics; - for (i = 0; i < Elements(src->_VertexAttrib); i++) + for (i = 0; i < Elements(src->_VertexAttrib); i++) { _mesa_copy_client_array(ctx, &dest->_VertexAttrib[i], &src->_VertexAttrib[i]); + _mesa_copy_vertex_attrib_array(ctx, &dest->VertexAttrib[i], &src->VertexAttrib[i]); + _mesa_copy_vertex_buffer_binding(ctx, &dest->VertexBinding[i], &src->VertexBinding[i]); + } /* _Enabled must be the same than on push */ dest->_Enabled = src->_Enabled; diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c index 15ec40c692b..b27f592e842 100644 --- a/src/mesa/main/bufferobj.c +++ b/src/mesa/main/bufferobj.c @@ -864,8 +864,8 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids) } /* unbind any vertex pointers bound to this buffer */ - for (j = 0; j < Elements(arrayObj->_VertexAttrib); j++) { - unbind(ctx, &arrayObj->_VertexAttrib[j].BufferObj, bufObj); + for (j = 0; j < Elements(arrayObj->VertexBinding); j++) { + unbind(ctx, &arrayObj->VertexBinding[j].BufferObj, bufObj); } if (ctx->Array.ArrayBufferObj == bufObj) { diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 6cdeed19b0a..49dbb55b886 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -678,6 +678,10 @@ _mesa_init_constants(struct gl_context *ctx) ctx->Const.MaxAtomicBufferSize = MAX_ATOMIC_COUNTERS * ATOMIC_COUNTER_SIZE; ctx->Const.MaxCombinedAtomicBuffers = MAX_COMBINED_ATOMIC_BUFFERS; ctx->Const.MaxCombinedAtomicCounters = MAX_ATOMIC_COUNTERS; + + /* GL_ARB_vertex_attrib_binding */ + ctx->Const.MaxVertexAttribRelativeOffset = 2047; + ctx->Const.MaxVertexAttribBindings = MAX_VERTEX_GENERIC_ATTRIBS; } diff --git a/src/mesa/main/enable.c b/src/mesa/main/enable.c index 255e25f27a9..c047f5df2c5 100644 --- a/src/mesa/main/enable.c +++ b/src/mesa/main/enable.c @@ -69,40 +69,40 @@ client_state(struct gl_context *ctx, GLenum cap, GLboolean state) switch (cap) { case GL_VERTEX_ARRAY: - var = &arrayObj->_VertexAttrib[VERT_ATTRIB_POS].Enabled; + var = &arrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled; flag = VERT_BIT_POS; break; case GL_NORMAL_ARRAY: - var = &arrayObj->_VertexAttrib[VERT_ATTRIB_NORMAL].Enabled; + var = &arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Enabled; flag = VERT_BIT_NORMAL; break; case GL_COLOR_ARRAY: - var = &arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR0].Enabled; + var = &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Enabled; flag = VERT_BIT_COLOR0; break; case GL_INDEX_ARRAY: - var = &arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled; + var = &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled; flag = VERT_BIT_COLOR_INDEX; break; case GL_TEXTURE_COORD_ARRAY: - var = &arrayObj->_VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)].Enabled; + var = &arrayObj->VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)].Enabled; flag = VERT_BIT_TEX(ctx->Array.ActiveTexture); break; case GL_EDGE_FLAG_ARRAY: - var = &arrayObj->_VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled; + var = &arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled; flag = VERT_BIT_EDGEFLAG; break; case GL_FOG_COORDINATE_ARRAY_EXT: - var = &arrayObj->_VertexAttrib[VERT_ATTRIB_FOG].Enabled; + var = &arrayObj->VertexAttrib[VERT_ATTRIB_FOG].Enabled; flag = VERT_BIT_FOG; break; case GL_SECONDARY_COLOR_ARRAY_EXT: - var = &arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR1].Enabled; + var = &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1].Enabled; flag = VERT_BIT_COLOR1; break; case GL_POINT_SIZE_ARRAY_OES: - var = &arrayObj->_VertexAttrib[VERT_ATTRIB_POINT_SIZE].Enabled; + var = &arrayObj->VertexAttrib[VERT_ATTRIB_POINT_SIZE].Enabled; flag = VERT_BIT_POINT_SIZE; break; @@ -1417,41 +1417,41 @@ _mesa_IsEnabled( GLenum cap ) case GL_VERTEX_ARRAY: if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES) goto invalid_enum_error; - return ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_POS].Enabled; + return ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled; case GL_NORMAL_ARRAY: if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES) goto invalid_enum_error; - return ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_NORMAL].Enabled; + return ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Enabled; case GL_COLOR_ARRAY: if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES) goto invalid_enum_error; - return ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_COLOR0].Enabled; + return ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Enabled; case GL_INDEX_ARRAY: if (ctx->API != API_OPENGL_COMPAT) goto invalid_enum_error; return ctx->Array.ArrayObj-> - _VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled; + VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled; case GL_TEXTURE_COORD_ARRAY: if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES) goto invalid_enum_error; return ctx->Array.ArrayObj-> - _VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)].Enabled; + VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)].Enabled; case GL_EDGE_FLAG_ARRAY: if (ctx->API != API_OPENGL_COMPAT) goto invalid_enum_error; - return ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled; + return ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled; case GL_FOG_COORDINATE_ARRAY_EXT: if (ctx->API != API_OPENGL_COMPAT) goto invalid_enum_error; - return ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_FOG].Enabled; + return ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_FOG].Enabled; case GL_SECONDARY_COLOR_ARRAY_EXT: if (ctx->API != API_OPENGL_COMPAT) goto invalid_enum_error; - return ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_COLOR1].Enabled; + return ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR1].Enabled; case GL_POINT_SIZE_ARRAY_OES: if (ctx->API != API_OPENGLES) goto invalid_enum_error; - return ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_POINT_SIZE].Enabled; + return ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POINT_SIZE].Enabled; /* GL_ARB_texture_cube_map */ case GL_TEXTURE_CUBE_MAP_ARB: diff --git a/src/mesa/main/ffvertex_prog.c b/src/mesa/main/ffvertex_prog.c index 08665c6b6f9..be6ac0f2af5 100644 --- a/src/mesa/main/ffvertex_prog.c +++ b/src/mesa/main/ffvertex_prog.c @@ -228,7 +228,7 @@ static void make_state_key( struct gl_context *ctx, struct state_key *key ) if (ctx->Point._Attenuated) key->point_attenuated = 1; - if (ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_POINT_SIZE].Enabled) + if (ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POINT_SIZE].Enabled) key->point_array = 1; if (ctx->Texture._TexGenEnabled || diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c index d41e73ec1b3..a0dd7cf4fb4 100644 --- a/src/mesa/main/get.c +++ b/src/mesa/main/get.c @@ -550,7 +550,7 @@ static void find_custom_value(struct gl_context *ctx, const struct value_desc *d, union value *v) { struct gl_buffer_object **buffer_obj; - struct gl_client_array *array; + struct gl_vertex_attrib_array *array; GLuint unit, *p; switch (d->pname) { @@ -629,7 +629,7 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu case GL_TEXTURE_COORD_ARRAY_SIZE: case GL_TEXTURE_COORD_ARRAY_TYPE: case GL_TEXTURE_COORD_ARRAY_STRIDE: - array = &ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)]; + array = &ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)]; v->value_int = *(GLuint *) ((char *) array + d->offset); break; @@ -775,7 +775,7 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu break; case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB: v->value_int = - ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)].BufferObj->Name; + ctx->Array.ArrayObj->VertexBinding[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)].BufferObj->Name; break; case GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB: v->value_int = ctx->Array.ArrayObj->ElementArrayBufferObj->Name; @@ -819,7 +819,7 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu ctx->CurrentRenderbuffer ? ctx->CurrentRenderbuffer->Name : 0; break; case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES: - v->value_int = ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_POINT_SIZE].BufferObj->Name; + v->value_int = ctx->Array.ArrayObj->VertexBinding[VERT_ATTRIB_POINT_SIZE].BufferObj->Name; break; case GL_FOG_COLOR: diff --git a/src/mesa/main/get_hash_params.py b/src/mesa/main/get_hash_params.py index cc0c5cd714f..5ecfbbc4d2a 100644 --- a/src/mesa/main/get_hash_params.py +++ b/src/mesa/main/get_hash_params.py @@ -191,17 +191,17 @@ descriptor=[ [ "TEXTURE_2D", "LOC_CUSTOM, TYPE_BOOLEAN, 0, NO_EXTRA" ], [ "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", "ARRAY_BOOL(_VertexAttrib[VERT_ATTRIB_POS].Enabled), NO_EXTRA" ], - [ "VERTEX_ARRAY_SIZE", "ARRAY_INT(_VertexAttrib[VERT_ATTRIB_POS].Size), NO_EXTRA" ], - [ "VERTEX_ARRAY_TYPE", "ARRAY_ENUM(_VertexAttrib[VERT_ATTRIB_POS].Type), NO_EXTRA" ], - [ "VERTEX_ARRAY_STRIDE", "ARRAY_INT(_VertexAttrib[VERT_ATTRIB_POS].Stride), NO_EXTRA" ], - [ "NORMAL_ARRAY", "ARRAY_BOOL(_VertexAttrib[VERT_ATTRIB_NORMAL].Enabled), NO_EXTRA" ], - [ "NORMAL_ARRAY_TYPE", "ARRAY_ENUM(_VertexAttrib[VERT_ATTRIB_NORMAL].Type), NO_EXTRA" ], - [ "NORMAL_ARRAY_STRIDE", "ARRAY_INT(_VertexAttrib[VERT_ATTRIB_NORMAL].Stride), NO_EXTRA" ], - [ "COLOR_ARRAY", "ARRAY_BOOL(_VertexAttrib[VERT_ATTRIB_COLOR0].Enabled), NO_EXTRA" ], - [ "COLOR_ARRAY_SIZE", "ARRAY_INT(_VertexAttrib[VERT_ATTRIB_COLOR0].Size), NO_EXTRA" ], - [ "COLOR_ARRAY_TYPE", "ARRAY_ENUM(_VertexAttrib[VERT_ATTRIB_COLOR0].Type), NO_EXTRA" ], - [ "COLOR_ARRAY_STRIDE", "ARRAY_INT(_VertexAttrib[VERT_ATTRIB_COLOR0].Stride), NO_EXTRA" ], + [ "VERTEX_ARRAY", "ARRAY_BOOL(VertexAttrib[VERT_ATTRIB_POS].Enabled), NO_EXTRA" ], + [ "VERTEX_ARRAY_SIZE", "ARRAY_INT(VertexAttrib[VERT_ATTRIB_POS].Size), NO_EXTRA" ], + [ "VERTEX_ARRAY_TYPE", "ARRAY_ENUM(VertexAttrib[VERT_ATTRIB_POS].Type), NO_EXTRA" ], + [ "VERTEX_ARRAY_STRIDE", "ARRAY_INT(VertexAttrib[VERT_ATTRIB_POS].Stride), NO_EXTRA" ], + [ "NORMAL_ARRAY", "ARRAY_BOOL(VertexAttrib[VERT_ATTRIB_NORMAL].Enabled), NO_EXTRA" ], + [ "NORMAL_ARRAY_TYPE", "ARRAY_ENUM(VertexAttrib[VERT_ATTRIB_NORMAL].Type), NO_EXTRA" ], + [ "NORMAL_ARRAY_STRIDE", "ARRAY_INT(VertexAttrib[VERT_ATTRIB_NORMAL].Stride), NO_EXTRA" ], + [ "COLOR_ARRAY", "ARRAY_BOOL(VertexAttrib[VERT_ATTRIB_COLOR0].Enabled), NO_EXTRA" ], + [ "COLOR_ARRAY_SIZE", "ARRAY_INT(VertexAttrib[VERT_ATTRIB_COLOR0].Size), NO_EXTRA" ], + [ "COLOR_ARRAY_TYPE", "ARRAY_ENUM(VertexAttrib[VERT_ATTRIB_COLOR0].Type), NO_EXTRA" ], + [ "COLOR_ARRAY_STRIDE", "ARRAY_INT(VertexAttrib[VERT_ATTRIB_COLOR0].Stride), NO_EXTRA" ], [ "TEXTURE_COORD_ARRAY", "LOC_CUSTOM, TYPE_BOOLEAN, offsetof(struct gl_client_array, Enabled), NO_EXTRA" ], [ "TEXTURE_COORD_ARRAY_SIZE", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_client_array, Size), NO_EXTRA" ], [ "TEXTURE_COORD_ARRAY_TYPE", "LOC_CUSTOM, TYPE_ENUM, offsetof(struct gl_client_array, Type), NO_EXTRA" ], @@ -221,9 +221,9 @@ descriptor=[ [ "SAMPLE_ALPHA_TO_ONE_ARB", "CONTEXT_BOOL(Multisample.SampleAlphaToOne), NO_EXTRA" ], # GL_ARB_vertex_buffer_object - [ "VERTEX_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, _VertexAttrib[VERT_ATTRIB_POS].BufferObj), NO_EXTRA" ], - [ "NORMAL_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, _VertexAttrib[VERT_ATTRIB_NORMAL].BufferObj), NO_EXTRA" ], - [ "COLOR_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, _VertexAttrib[VERT_ATTRIB_COLOR0].BufferObj), NO_EXTRA" ], + [ "VERTEX_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexBinding[VERT_ATTRIB_POS].BufferObj), NO_EXTRA" ], + [ "NORMAL_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexBinding[VERT_ATTRIB_NORMAL].BufferObj), NO_EXTRA" ], + [ "COLOR_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexBinding[VERT_ATTRIB_COLOR0].BufferObj), NO_EXTRA" ], [ "TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, NO_OFFSET, NO_EXTRA" ], # GL_OES_point_sprite @@ -233,9 +233,9 @@ descriptor=[ { "apis": ["GLES"], "params": [ # OES_point_size_array - [ "POINT_SIZE_ARRAY_OES", "ARRAY_FIELD(_VertexAttrib[VERT_ATTRIB_POINT_SIZE].Enabled, TYPE_BOOLEAN)" ], - [ "POINT_SIZE_ARRAY_TYPE_OES", "ARRAY_FIELD(_VertexAttrib[VERT_ATTRIB_POINT_SIZE].Type, TYPE_ENUM)" ], - [ "POINT_SIZE_ARRAY_STRIDE_OES", "ARRAY_FIELD(_VertexAttrib[VERT_ATTRIB_POINT_SIZE].Stride, TYPE_INT)" ], + [ "POINT_SIZE_ARRAY_OES", "ARRAY_FIELD(VertexAttrib[VERT_ATTRIB_POINT_SIZE].Enabled, TYPE_BOOLEAN)" ], + [ "POINT_SIZE_ARRAY_TYPE_OES", "ARRAY_FIELD(VertexAttrib[VERT_ATTRIB_POINT_SIZE].Type, TYPE_ENUM)" ], + [ "POINT_SIZE_ARRAY_STRIDE_OES", "ARRAY_FIELD(VertexAttrib[VERT_ATTRIB_POINT_SIZE].Stride, TYPE_INT)" ], [ "POINT_SIZE_ARRAY_BUFFER_BINDING_OES", "LOC_CUSTOM, TYPE_INT, 0" ], ]}, @@ -521,13 +521,13 @@ descriptor=[ [ "VERTEX_ARRAY_COUNT_EXT", "CONST(0), NO_EXTRA" ], [ "NORMAL_ARRAY_COUNT_EXT", "CONST(0), NO_EXTRA" ], [ "COLOR_ARRAY_COUNT_EXT", "CONST(0), NO_EXTRA" ], - [ "INDEX_ARRAY", "ARRAY_BOOL(_VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled), NO_EXTRA" ], - [ "INDEX_ARRAY_TYPE", "ARRAY_ENUM(_VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Type), NO_EXTRA" ], - [ "INDEX_ARRAY_STRIDE", "ARRAY_INT(_VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Stride), NO_EXTRA" ], + [ "INDEX_ARRAY", "ARRAY_BOOL(VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled), NO_EXTRA" ], + [ "INDEX_ARRAY_TYPE", "ARRAY_ENUM(VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Type), NO_EXTRA" ], + [ "INDEX_ARRAY_STRIDE", "ARRAY_INT(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" ], - [ "EDGE_FLAG_ARRAY", "ARRAY_BOOL(_VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled), NO_EXTRA" ], - [ "EDGE_FLAG_ARRAY_STRIDE", "ARRAY_INT(_VertexAttrib[VERT_ATTRIB_EDGEFLAG].Stride), NO_EXTRA" ], + [ "EDGE_FLAG_ARRAY", "ARRAY_BOOL(VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled), NO_EXTRA" ], + [ "EDGE_FLAG_ARRAY_STRIDE", "ARRAY_INT(VertexAttrib[VERT_ATTRIB_EDGEFLAG].Stride), NO_EXTRA" ], [ "EDGE_FLAG_ARRAY_COUNT_EXT", "CONST(0), NO_EXTRA" ], # GL_ARB_texture_compression @@ -545,16 +545,16 @@ descriptor=[ # GL_EXT_secondary_color [ "COLOR_SUM", "CONTEXT_BOOL(Fog.ColorSumEnabled), extra_ARB_vertex_program" ], [ "CURRENT_SECONDARY_COLOR", "CONTEXT_FIELD(Current.Attrib[VERT_ATTRIB_COLOR1][0], TYPE_FLOATN_4), extra_flush_current" ], - [ "SECONDARY_COLOR_ARRAY", "ARRAY_BOOL(_VertexAttrib[VERT_ATTRIB_COLOR1].Enabled), NO_EXTRA" ], - [ "SECONDARY_COLOR_ARRAY_TYPE", "ARRAY_ENUM(_VertexAttrib[VERT_ATTRIB_COLOR1].Type), NO_EXTRA" ], - [ "SECONDARY_COLOR_ARRAY_STRIDE", "ARRAY_INT(_VertexAttrib[VERT_ATTRIB_COLOR1].Stride), NO_EXTRA" ], - [ "SECONDARY_COLOR_ARRAY_SIZE", "ARRAY_INT(_VertexAttrib[VERT_ATTRIB_COLOR1].Size), NO_EXTRA" ], + [ "SECONDARY_COLOR_ARRAY", "ARRAY_BOOL(VertexAttrib[VERT_ATTRIB_COLOR1].Enabled), NO_EXTRA" ], + [ "SECONDARY_COLOR_ARRAY_TYPE", "ARRAY_ENUM(VertexAttrib[VERT_ATTRIB_COLOR1].Type), NO_EXTRA" ], + [ "SECONDARY_COLOR_ARRAY_STRIDE", "ARRAY_INT(VertexAttrib[VERT_ATTRIB_COLOR1].Stride), NO_EXTRA" ], + [ "SECONDARY_COLOR_ARRAY_SIZE", "ARRAY_INT(VertexAttrib[VERT_ATTRIB_COLOR1].Size), NO_EXTRA" ], # GL_EXT_fog_coord [ "CURRENT_FOG_COORDINATE", "CONTEXT_FLOAT(Current.Attrib[VERT_ATTRIB_FOG][0]), extra_flush_current" ], - [ "FOG_COORDINATE_ARRAY", "ARRAY_BOOL(_VertexAttrib[VERT_ATTRIB_FOG].Enabled), NO_EXTRA" ], - [ "FOG_COORDINATE_ARRAY_TYPE", "ARRAY_ENUM(_VertexAttrib[VERT_ATTRIB_FOG].Type), NO_EXTRA" ], - [ "FOG_COORDINATE_ARRAY_STRIDE", "ARRAY_INT(_VertexAttrib[VERT_ATTRIB_FOG].Stride), NO_EXTRA" ], + [ "FOG_COORDINATE_ARRAY", "ARRAY_BOOL(VertexAttrib[VERT_ATTRIB_FOG].Enabled), NO_EXTRA" ], + [ "FOG_COORDINATE_ARRAY_TYPE", "ARRAY_ENUM(VertexAttrib[VERT_ATTRIB_FOG].Type), NO_EXTRA" ], + [ "FOG_COORDINATE_ARRAY_STRIDE", "ARRAY_INT(VertexAttrib[VERT_ATTRIB_FOG].Stride), NO_EXTRA" ], [ "FOG_COORDINATE_SOURCE", "CONTEXT_ENUM(Fog.FogCoordinateSource), NO_EXTRA" ], # GL_NV_fog_distance @@ -585,10 +585,10 @@ descriptor=[ [ "PRIMITIVE_RESTART_INDEX_NV", "CONTEXT_INT(Array.RestartIndex), extra_NV_primitive_restart" ], # GL_ARB_vertex_buffer_object - [ "INDEX_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, _VertexAttrib[VERT_ATTRIB_COLOR_INDEX].BufferObj), NO_EXTRA" ], - [ "EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, _VertexAttrib[VERT_ATTRIB_EDGEFLAG].BufferObj), NO_EXTRA" ], - [ "SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, _VertexAttrib[VERT_ATTRIB_COLOR1].BufferObj), NO_EXTRA" ], - [ "FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, _VertexAttrib[VERT_ATTRIB_FOG].BufferObj), NO_EXTRA" ], + [ "INDEX_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexBinding[VERT_ATTRIB_COLOR_INDEX].BufferObj), NO_EXTRA" ], + [ "EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexBinding[VERT_ATTRIB_EDGEFLAG].BufferObj), NO_EXTRA" ], + [ "SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexBinding[VERT_ATTRIB_COLOR1].BufferObj), NO_EXTRA" ], + [ "FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexBinding[VERT_ATTRIB_FOG].BufferObj), NO_EXTRA" ], # GL_ARB_vertex_program # == GL_VERTEX_PROGRAM_NV diff --git a/src/mesa/main/getstring.c b/src/mesa/main/getstring.c index 60ffaa19879..0e075427fa0 100644 --- a/src/mesa/main/getstring.c +++ b/src/mesa/main/getstring.c @@ -202,42 +202,42 @@ _mesa_GetPointerv( GLenum pname, GLvoid **params ) case GL_VERTEX_ARRAY_POINTER: if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES) goto invalid_pname; - *params = (GLvoid *) ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_POS].Ptr; + *params = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POS].Ptr; break; case GL_NORMAL_ARRAY_POINTER: if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES) goto invalid_pname; - *params = (GLvoid *) ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_NORMAL].Ptr; + *params = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Ptr; break; case GL_COLOR_ARRAY_POINTER: if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES) goto invalid_pname; - *params = (GLvoid *) ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_COLOR0].Ptr; + *params = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Ptr; break; case GL_SECONDARY_COLOR_ARRAY_POINTER_EXT: if (ctx->API != API_OPENGL_COMPAT) goto invalid_pname; - *params = (GLvoid *) ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_COLOR1].Ptr; + *params = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR1].Ptr; break; case GL_FOG_COORDINATE_ARRAY_POINTER_EXT: if (ctx->API != API_OPENGL_COMPAT) goto invalid_pname; - *params = (GLvoid *) ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_FOG].Ptr; + *params = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_FOG].Ptr; break; case GL_INDEX_ARRAY_POINTER: if (ctx->API != API_OPENGL_COMPAT) goto invalid_pname; - *params = (GLvoid *) ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Ptr; + *params = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Ptr; break; case GL_TEXTURE_COORD_ARRAY_POINTER: if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES) goto invalid_pname; - *params = (GLvoid *) ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_TEX(clientUnit)].Ptr; + *params = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_TEX(clientUnit)].Ptr; break; case GL_EDGE_FLAG_ARRAY_POINTER: if (ctx->API != API_OPENGL_COMPAT) goto invalid_pname; - *params = (GLvoid *) ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_EDGEFLAG].Ptr; + *params = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Ptr; break; case GL_FEEDBACK_BUFFER_POINTER: if (ctx->API != API_OPENGL_COMPAT) @@ -252,7 +252,7 @@ _mesa_GetPointerv( GLenum pname, GLvoid **params ) case GL_POINT_SIZE_ARRAY_POINTER_OES: if (ctx->API != API_OPENGLES) goto invalid_pname; - *params = (GLvoid *) ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_POINT_SIZE].Ptr; + *params = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POINT_SIZE].Ptr; break; case GL_DEBUG_CALLBACK_FUNCTION_ARB: if (!_mesa_is_desktop_gl(ctx)) diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 0fd9c1489eb..3f0e3ead723 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1473,6 +1473,44 @@ struct gl_client_array }; +/** + * Vertex attribute array as seen by the client. + * + * Contains the size, type, format and normalization flag, + * along with the index of a vertex buffer binding point. + * + * Note that the Stride field corresponds to VERTEX_ATTRIB_ARRAY_STRIDE + * and is only present for backwards compatibility reasons. + * Rendering always uses VERTEX_BINDING_STRIDE. + * The gl*Pointer() functions will set VERTEX_ATTRIB_ARRAY_STRIDE + * and VERTEX_BINDING_STRIDE to the same value, while + * glBindVertexBuffer() will only set VERTEX_BINDING_STRIDE. + */ +struct gl_vertex_attrib_array +{ + GLint Size; /**< Components per element (1,2,3,4) */ + GLenum Type; /**< Datatype: GL_FLOAT, GL_INT, etc */ + GLenum Format; /**< Default: GL_RGBA, but may be GL_BGRA */ + GLsizei Stride; /**< Stride as specified with gl*Pointer() */ + const GLubyte *Ptr; /**< Points to client array data. Not used when a VBO is bound */ + GLintptr RelativeOffset; /**< Offset of the first element relative to the binding offset */ + GLboolean Enabled; /**< Whether the array is enabled */ + GLboolean Normalized; /**< Fixed-point values are normalized when converted to floats */ + GLboolean Integer; /**< Fixed-point values are not converted to floats */ + GLuint _ElementSize; /**< Size of each element in bytes */ + GLuint VertexBinding; /**< Vertex buffer binding */ +}; + +struct gl_vertex_buffer_binding +{ + GLintptr Offset; /**< User-specified offset */ + GLsizei Stride; /**< User-specified stride */ + GLuint InstanceDivisor; /**< GL_ARB_instanced_arrays */ + struct gl_buffer_object *BufferObj; /**< GL_ARB_vertex_buffer_object */ + GLbitfield64 _BoundArrays; /**< Arrays bound to this binding point */ +}; + + /** * Collection of vertex arrays. Defined by the GL_APPLE_vertex_array_object * extension, but a nice encapsulation in any case. @@ -1507,9 +1545,15 @@ struct gl_array_object */ GLboolean EverBound; - /** Vertex attribute arrays */ + /** Derived vertex attribute arrays */ struct gl_client_array _VertexAttrib[VERT_ATTRIB_MAX]; + /** Vertex attribute arrays */ + struct gl_vertex_attrib_array VertexAttrib[VERT_ATTRIB_MAX]; + + /** Vertex buffer bindings */ + struct gl_vertex_buffer_binding VertexBinding[VERT_ATTRIB_MAX]; + /** Mask of VERT_BIT_* values indicating which arrays are enabled */ GLbitfield64 _Enabled; @@ -3216,6 +3260,10 @@ struct gl_constants GLuint MaxAtomicBufferSize; GLuint MaxCombinedAtomicBuffers; GLuint MaxCombinedAtomicCounters; + + /** GL_ARB_vertex_attrib_binding */ + GLint MaxVertexAttribRelativeOffset; + GLint MaxVertexAttribBindings; }; diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index bf216312b83..33070b7e02d 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -410,6 +410,9 @@ _mesa_update_state_locked( struct gl_context *ctx ) new_prog_state |= update_program( ctx ); } + if (new_state & _NEW_ARRAY) + _mesa_update_array_object_client_arrays(ctx, ctx->Array.ArrayObj); + if (ctx->Const.CheckArrayBounds && new_state & (_NEW_ARRAY | _NEW_PROGRAM | _NEW_BUFFER_OBJECT)) { _mesa_update_array_object_max_element(ctx, ctx->Array.ArrayObj); diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c index a705b6b9368..b0e02865b1d 100644 --- a/src/mesa/main/varray.c +++ b/src/mesa/main/varray.c @@ -102,20 +102,94 @@ type_to_bit(const struct gl_context *ctx, GLenum type) } +/** + * Sets the VertexBinding field in the vertex attribute given by attribIndex. + */ +static void +vertex_attrib_binding(struct gl_context *ctx, GLuint attribIndex, + GLuint bindingIndex) +{ + struct gl_array_object *arrayObj = ctx->Array.ArrayObj; + struct gl_vertex_attrib_array *array = &arrayObj->VertexAttrib[attribIndex]; + + if (array->VertexBinding != bindingIndex) { + const GLbitfield64 array_bit = VERT_BIT(attribIndex); + + FLUSH_VERTICES(ctx, _NEW_ARRAY); + + arrayObj->VertexBinding[array->VertexBinding]._BoundArrays &= ~array_bit; + arrayObj->VertexBinding[bindingIndex]._BoundArrays |= array_bit; + + array->VertexBinding = bindingIndex; + + arrayObj->NewArrays |= array_bit; + } +} + + +/** + * Binds a buffer object to the vertex buffer binding point given by index, + * and sets the Offset and Stride fields. + */ +static void +bind_vertex_buffer(struct gl_context *ctx, GLuint index, + struct gl_buffer_object *vbo, + GLintptr offset, GLsizei stride) +{ + struct gl_array_object *arrayObj = ctx->Array.ArrayObj; + struct gl_vertex_buffer_binding *binding = &arrayObj->VertexBinding[index]; + + if (binding->BufferObj != vbo || + binding->Offset != offset || + binding->Stride != stride) { + + FLUSH_VERTICES(ctx, _NEW_ARRAY); + + _mesa_reference_buffer_object(ctx, &binding->BufferObj, vbo); + + binding->Offset = offset; + binding->Stride = stride; + + arrayObj->NewArrays |= binding->_BoundArrays; + } +} + + +/** + * Sets the InstanceDivisor field in the vertex buffer binding point + * given by bindingIndex. + */ +static void +vertex_binding_divisor(struct gl_context *ctx, GLuint bindingIndex, + GLuint divisor) +{ + struct gl_array_object *arrayObj = ctx->Array.ArrayObj; + struct gl_vertex_buffer_binding *binding = + &arrayObj->VertexBinding[bindingIndex]; + + if (binding->InstanceDivisor != divisor) { + FLUSH_VERTICES(ctx, _NEW_ARRAY); + binding->InstanceDivisor = divisor; + arrayObj->NewArrays |= binding->_BoundArrays; + } +} + + /** * Does error checking and updates the format in an attrib array. * - * Called by update_array(). + * Called by update_array() and VertexAttrib*Format(). * - * \param func Name of calling function used for error reporting - * \param attrib The index of the attribute array - * \param legalTypes Bitmask of *_BIT above indicating legal datatypes - * \param sizeMin Min allowable size value - * \param sizeMax Max allowable size value (may also be BGRA_OR_4) - * \param size Components per element (1, 2, 3 or 4) - * \param type Datatype of each component (GL_FLOAT, GL_INT, etc) - * \param normalized Whether integer types are converted to floats in [-1, 1] - * \param integer Integer-valued values (will not be normalized to [-1, 1]) + * \param func Name of calling function used for error reporting + * \param attrib The index of the attribute array + * \param legalTypes Bitmask of *_BIT above indicating legal datatypes + * \param sizeMin Min allowable size value + * \param sizeMax Max allowable size value (may also be BGRA_OR_4) + * \param size Components per element (1, 2, 3 or 4) + * \param type Datatype of each component (GL_FLOAT, GL_INT, etc) + * \param normalized Whether integer types are converted to floats in [-1, 1] + * \param integer Integer-valued values (will not be normalized to [-1, 1]) + * \param relativeOffset Offset of the first element relative to the binding offset. */ static bool update_array_format(struct gl_context *ctx, @@ -123,9 +197,10 @@ update_array_format(struct gl_context *ctx, GLuint attrib, GLbitfield legalTypesMask, GLint sizeMin, GLint sizeMax, GLint size, GLenum type, - GLboolean normalized, GLboolean integer) + GLboolean normalized, GLboolean integer, + GLuint relativeOffset) { - struct gl_client_array *array; + struct gl_vertex_attrib_array *array; GLbitfield typeBit; GLuint elementSize; GLenum format = GL_RGBA; @@ -224,19 +299,36 @@ update_array_format(struct gl_context *ctx, return false; } + /* The ARB_vertex_attrib_binding_spec says: + * + * An INVALID_VALUE error is generated if is larger than + * the value of MAX_VERTEX_ATTRIB_RELATIVE_OFFSET. + */ + if (relativeOffset > ctx->Const.MaxVertexAttribRelativeOffset) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(relativeOffset=%d > " + "GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET)", + func, relativeOffset); + return GL_FALSE; + } + ASSERT(size <= 4); elementSize = _mesa_bytes_per_vertex_attrib(size, type); assert(elementSize != -1); - array = &ctx->Array.ArrayObj->_VertexAttrib[attrib]; + array = &ctx->Array.ArrayObj->VertexAttrib[attrib]; array->Size = size; array->Type = type; array->Format = format; array->Normalized = normalized; array->Integer = integer; + array->RelativeOffset = relativeOffset; array->_ElementSize = elementSize; + ctx->Array.ArrayObj->NewArrays |= VERT_BIT(attrib); + ctx->NewState |= _NEW_ARRAY; + return true; } @@ -266,7 +358,8 @@ update_array(struct gl_context *ctx, GLboolean normalized, GLboolean integer, const GLvoid *ptr) { - struct gl_client_array *array; + struct gl_vertex_attrib_array *array; + GLsizei effectiveStride; /* Page 407 (page 423 of the PDF) of the OpenGL 3.0 spec says: * @@ -286,7 +379,7 @@ update_array(struct gl_context *ctx, } if (!update_array_format(ctx, func, attrib, legalTypesMask, sizeMin, sizeMax, - size, type, normalized, integer)) { + size, type, normalized, integer, 0)) { return; } @@ -313,16 +406,18 @@ update_array(struct gl_context *ctx, return; } - array = &ctx->Array.ArrayObj->_VertexAttrib[attrib]; - array->Stride = stride; - array->StrideB = stride ? stride : array->_ElementSize; - array->Ptr = (const GLubyte *) ptr; + /* Reset the vertex attrib binding */ + vertex_attrib_binding(ctx, attrib, attrib); - _mesa_reference_buffer_object(ctx, &array->BufferObj, - ctx->Array.ArrayBufferObj); + /* The Stride and Ptr fields are not set by update_array_format() */ + array = &ctx->Array.ArrayObj->VertexAttrib[attrib]; + array->Stride = stride; + array->Ptr = (const GLvoid *) ptr; - ctx->NewState |= _NEW_ARRAY; - ctx->Array.ArrayObj->NewArrays |= VERT_BIT(attrib); + /* Update the vertex buffer binding */ + effectiveStride = stride != 0 ? stride : array->_ElementSize; + bind_vertex_buffer(ctx, attrib, ctx->Array.ArrayBufferObj, + (GLintptr) ptr, effectiveStride); } @@ -569,10 +664,10 @@ _mesa_EnableVertexAttribArray(GLuint index) ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->_VertexAttrib)); - if (!arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) { + if (!arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) { /* was disabled, now being enabled */ FLUSH_VERTICES(ctx, _NEW_ARRAY); - arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled = GL_TRUE; + arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled = GL_TRUE; arrayObj->_Enabled |= VERT_BIT_GENERIC(index); arrayObj->NewArrays |= VERT_BIT_GENERIC(index); } @@ -595,10 +690,10 @@ _mesa_DisableVertexAttribArray(GLuint index) ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->_VertexAttrib)); - if (arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) { + if (arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) { /* was enabled, now being disabled */ FLUSH_VERTICES(ctx, _NEW_ARRAY); - arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled = GL_FALSE; + arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled = GL_FALSE; arrayObj->_Enabled &= ~VERT_BIT_GENERIC(index); arrayObj->NewArrays |= VERT_BIT_GENERIC(index); } @@ -614,16 +709,17 @@ static GLuint get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname, const char *caller) { - const struct gl_client_array *array; + const struct gl_array_object *arrayObj = ctx->Array.ArrayObj; + const struct gl_vertex_attrib_array *array; if (index >= ctx->Const.VertexProgram.MaxAttribs) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%u)", caller, index); return 0; } - ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->_VertexAttrib)); + ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->VertexAttrib)); - array = &ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(index)]; + array = &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)]; switch (pname) { case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB: @@ -637,7 +733,7 @@ get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname, case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB: return array->Normalized; case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB: - return array->BufferObj->Name; + return arrayObj->VertexBinding[array->VertexBinding].BufferObj->Name; case GL_VERTEX_ATTRIB_ARRAY_INTEGER: if ((_mesa_is_desktop_gl(ctx) && (ctx->Version >= 30 || ctx->Extensions.EXT_gpu_shader4)) @@ -648,7 +744,7 @@ get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname, case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB: if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_instanced_arrays) || _mesa_is_gles3(ctx)) { - return array->InstanceDivisor; + return arrayObj->VertexBinding[array->VertexBinding].InstanceDivisor; } goto error; default: @@ -806,7 +902,7 @@ _mesa_GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid **pointer) ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->_VertexAttrib)); - *pointer = (GLvoid *) ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(index)].Ptr; + *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Ptr; } @@ -1180,9 +1276,10 @@ _mesa_PrimitiveRestartIndex(GLuint index) void GLAPIENTRY _mesa_VertexAttribDivisor(GLuint index, GLuint divisor) { - struct gl_client_array *array; GET_CURRENT_CONTEXT(ctx); + const GLuint genericIndex = VERT_ATTRIB_GENERIC(index); + if (!ctx->Extensions.ARB_instanced_arrays) { _mesa_error(ctx, GL_INVALID_OPERATION, "glVertexAttribDivisor()"); return; @@ -1194,14 +1291,21 @@ _mesa_VertexAttribDivisor(GLuint index, GLuint divisor) return; } - ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->_VertexAttrib)); + ASSERT(genericIndex < Elements(ctx->Array.ArrayObj->VertexAttrib)); - array = &ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(index)]; - if (array->InstanceDivisor != divisor) { - FLUSH_VERTICES(ctx, _NEW_ARRAY); - array->InstanceDivisor = divisor; - ctx->Array.ArrayObj->NewArrays |= VERT_BIT(VERT_ATTRIB_GENERIC(index)); - } + /* The ARB_vertex_attrib_binding spec says: + * + * "The command + * + * void VertexAttribDivisor(uint index, uint divisor); + * + * is equivalent to (assuming no errors are generated): + * + * VertexAttribBinding(index, index); + * VertexBindingDivisor(index, divisor);" + */ + vertex_attrib_binding(ctx, genericIndex, genericIndex); + vertex_binding_divisor(ctx, genericIndex, divisor); } @@ -1237,6 +1341,80 @@ void GLAPIENTRY _mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset, GLsizei stride) { + struct gl_buffer_object *vbo; + + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + /* The ARB_vertex_attrib_binding spec says: + * + * "An INVALID_OPERATION error is generated if no vertex array object + * is bound." + */ + if (ctx->API == API_OPENGL_CORE && + ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindVertexBuffer(No array object bound)"); + return; + } + + /* The ARB_vertex_attrib_binding spec says: + * + * "An INVALID_VALUE error is generated if is greater than + * the value of MAX_VERTEX_ATTRIB_BINDINGS." + */ + if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glBindVertexBuffer(bindingindex=%u > " + "GL_MAX_VERTEX_ATTRIB_BINDINGS)", + bindingIndex); + return; + } + + /* The ARB_vertex_attrib_binding spec says: + * + * "The error INVALID_VALUE is generated if or + * are negative." + */ + if (offset < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glBindVertexBuffer(offset=%lld < 0)", (long long)offset); + return; + } + + if (stride < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glBindVertexBuffer(stride=%d < 0)", stride); + return; + } + + if (buffer != 0) { + vbo = _mesa_lookup_bufferobj(ctx, buffer); + + /* From the GL_ARB_vertex_attrib_array spec: + * + * "[Core profile only:] + * An INVALID_OPERATION error is generated if buffer is not zero or a + * name returned from a previous call to GenBuffers, or if such a name + * has since been deleted with DeleteBuffers. + * + * Otherwise, we fall back to the same compat profile behavior as other + * object references (automatically gen it). + */ + if (!_mesa_handle_bind_buffer_gen(ctx, GL_ARRAY_BUFFER, buffer, + &vbo, "glBindVertexBuffer")) + return; + } else { + /* The ARB_vertex_attrib_binding spec says: + * + * "If is zero, any buffer object attached to this + * bindpoint is detached." + */ + vbo = ctx->Shared->NullBufferObj; + } + + bind_vertex_buffer(ctx, VERT_ATTRIB_GENERIC(bindingIndex), + vbo, offset, stride); } @@ -1244,6 +1422,50 @@ void GLAPIENTRY _mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type, GLboolean normalized, GLuint relativeOffset) { + const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT | + SHORT_BIT | UNSIGNED_SHORT_BIT | + INT_BIT | UNSIGNED_INT_BIT | + HALF_BIT | FLOAT_BIT | DOUBLE_BIT | + FIXED_GL_BIT | + UNSIGNED_INT_2_10_10_10_REV_BIT | + INT_2_10_10_10_REV_BIT); + + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + /* The ARB_vertex_attrib_binding spec says: + * + * "An INVALID_OPERATION error is generated under any of the following + * conditions: + * - if no vertex array object is currently bound (see section 2.10); + * - ..." + */ + if (ctx->API == API_OPENGL_CORE && + ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glVertexAttribFormat(No array object bound)"); + return; + } + + /* The ARB_vertex_attrib_binding spec says: + * + * "The error INVALID_VALUE is generated if index is greater than or equal + * to the value of MAX_VERTEX_ATTRIBS." + */ + if (attribIndex >= ctx->Const.VertexProgram.MaxAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glVertexAttribFormat(attribindex=%u > " + "GL_MAX_VERTEX_ATTRIBS)", + attribIndex); + return; + } + + FLUSH_VERTICES(ctx, 0); + + update_array_format(ctx, "glVertexAttribFormat", + VERT_ATTRIB_GENERIC(attribIndex), + legalTypes, 1, BGRA_OR_4, size, type, normalized, + GL_FALSE, relativeOffset); } @@ -1251,6 +1473,46 @@ void GLAPIENTRY _mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type, GLuint relativeOffset) { + const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT | + SHORT_BIT | UNSIGNED_SHORT_BIT | + INT_BIT | UNSIGNED_INT_BIT); + + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + /* The ARB_vertex_attrib_binding spec says: + * + * "An INVALID_OPERATION error is generated under any of the following + * conditions: + * - if no vertex array object is currently bound (see section 2.10); + * - ..." + */ + if (ctx->API == API_OPENGL_CORE && + ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glVertexAttribIFormat(No array object bound)"); + return; + } + + /* The ARB_vertex_attrib_binding spec says: + * + * "The error INVALID_VALUE is generated if index is greater than + * or equal to the value of MAX_VERTEX_ATTRIBS." + */ + if (attribIndex >= ctx->Const.VertexProgram.MaxAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glVertexAttribIFormat(attribindex=%u > " + "GL_MAX_VERTEX_ATTRIBS)", + attribIndex); + return; + } + + FLUSH_VERTICES(ctx, 0); + + update_array_format(ctx, "glVertexAttribIFormat", + VERT_ATTRIB_GENERIC(attribIndex), + legalTypes, 1, 4, size, type, GL_FALSE, GL_TRUE, + relativeOffset); } @@ -1258,18 +1520,136 @@ void GLAPIENTRY _mesa_VertexAttribLFormat(GLuint attribIndex, GLint size, GLenum type, GLuint relativeOffset) { + const GLbitfield legalTypes = DOUBLE_BIT; + + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + /* Page 298 of the PDF of the OpenGL 4.3 (Core Profile) spec says: + * + * "An INVALID_OPERATION error is generated under any of the following + * conditions: + * • if no vertex array object is currently bound (see section 10.4); + * • ..." + * + * This language is missing from the extension spec, but we assume + * that this is an oversight. + */ + if (ctx->API == API_OPENGL_CORE && + ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glVertexAttribLFormat(No array object bound)"); + return; + } + + /* The ARB_vertex_attrib_binding spec says: + * + * "The error INVALID_VALUE is generated if is greater than + * or equal to the value of MAX_VERTEX_ATTRIBS." + */ + if (attribIndex >= ctx->Const.VertexProgram.MaxAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glVertexAttribLFormat(attribindex=%u > " + "GL_MAX_VERTEX_ATTRIBS)", + attribIndex); + return; + } + + FLUSH_VERTICES(ctx, 0); + + update_array_format(ctx, "glVertexAttribLFormat", + VERT_ATTRIB_GENERIC(attribIndex), + legalTypes, 1, 4, size, type, GL_FALSE, GL_FALSE, + relativeOffset); } void GLAPIENTRY _mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex) { + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + /* The ARB_vertex_attrib_binding spec says: + * + * "An INVALID_OPERATION error is generated if no vertex array object + * is bound." + */ + if (ctx->API == API_OPENGL_CORE && + ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glVertexAttribBinding(No array object bound)"); + return; + } + + /* The ARB_vertex_attrib_binding spec says: + * + * " must be less than the value of MAX_VERTEX_ATTRIBS and + * must be less than the value of + * MAX_VERTEX_ATTRIB_BINDINGS, otherwise the error INVALID_VALUE + * is generated." + */ + if (attribIndex >= ctx->Const.VertexProgram.MaxAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glVertexAttribBinding(attribindex=%u >= " + "GL_MAX_VERTEX_ATTRIBS)", + attribIndex); + return; + } + + if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glVertexAttribBinding(bindingindex=%u >= " + "GL_MAX_VERTEX_ATTRIB_BINDINGS)", + bindingIndex); + return; + } + + ASSERT(VERT_ATTRIB_GENERIC(attribIndex) < + Elements(ctx->Array.ArrayObj->VertexAttrib)); + + vertex_attrib_binding(ctx, VERT_ATTRIB_GENERIC(attribIndex), + VERT_ATTRIB_GENERIC(bindingIndex)); } void GLAPIENTRY _mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor) { + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (!ctx->Extensions.ARB_instanced_arrays) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glVertexBindingDivisor()"); + return; + } + + /* The ARB_vertex_attrib_binding spec says: + * + * "An INVALID_OPERATION error is generated if no vertex array object + * is bound." + */ + if (ctx->API == API_OPENGL_CORE && + ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glVertexBindingDivisor(No array object bound)"); + return; + } + + /* The ARB_vertex_attrib_binding spec says: + * + * "An INVALID_VALUE error is generated if is greater + * than or equal to the value of MAX_VERTEX_ATTRIB_BINDINGS." + */ + if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glVertexBindingDivisor(bindingindex=%u > " + "GL_MAX_VERTEX_ATTRIB_BINDINGS)", + bindingIndex); + return; + } + + vertex_binding_divisor(ctx, VERT_ATTRIB_GENERIC(bindingIndex), divisor); } @@ -1296,7 +1676,36 @@ _mesa_copy_client_array(struct gl_context *ctx, dst->_MaxElement = src->_MaxElement; } +void +_mesa_copy_vertex_attrib_array(struct gl_context *ctx, + struct gl_vertex_attrib_array *dst, + const struct gl_vertex_attrib_array *src) +{ + dst->Size = src->Size; + dst->Type = src->Type; + dst->Format = src->Format; + dst->VertexBinding = src->VertexBinding; + dst->RelativeOffset = src->RelativeOffset; + dst->Format = src->Format; + dst->Integer = src->Integer; + dst->Normalized = src->Normalized; + dst->Ptr = src->Ptr; + dst->Enabled = src->Enabled; + dst->_ElementSize = src->_ElementSize; +} + +void +_mesa_copy_vertex_buffer_binding(struct gl_context *ctx, + struct gl_vertex_buffer_binding *dst, + const struct gl_vertex_buffer_binding *src) +{ + dst->Offset = src->Offset; + dst->Stride = src->Stride; + dst->InstanceDivisor = src->InstanceDivisor; + dst->_BoundArrays = src->_BoundArrays; + _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj); +} /** * Print vertex array's fields. diff --git a/src/mesa/main/varray.h b/src/mesa/main/varray.h index 2b54fde9836..a75cb7db8ea 100644 --- a/src/mesa/main/varray.h +++ b/src/mesa/main/varray.h @@ -29,6 +29,7 @@ #include "glheader.h" +#include "bufferobj.h" struct gl_client_array; struct gl_context; @@ -64,6 +65,44 @@ _mesa_update_array_max_element(struct gl_client_array *array) } +/** + * Returns a pointer to the vertex attribute data in a client array, + * or the offset into the vertex buffer for an array that resides in + * a vertex buffer. + */ +static inline const GLubyte * +_mesa_vertex_attrib_address(struct gl_vertex_attrib_array *array, + struct gl_vertex_buffer_binding *binding) +{ + return (binding->BufferObj->Name == 0 ? + array->Ptr : + (const GLubyte *)(binding->Offset + array->RelativeOffset)); +} + +/** + * Sets the fields in a gl_client_array to values derived from a + * gl_vertex_attrib_array and a gl_vertex_buffer_binding. + */ +static inline void +_mesa_update_client_array(struct gl_context *ctx, + struct gl_client_array *dst, + struct gl_vertex_attrib_array *src, + struct gl_vertex_buffer_binding *binding) +{ + dst->Size = src->Size; + dst->Type = src->Type; + dst->Format = src->Format; + dst->Stride = src->Stride; + dst->StrideB = binding->Stride; + dst->Ptr = _mesa_vertex_attrib_address(src, binding); + dst->Enabled = src->Enabled; + dst->Normalized = src->Normalized; + dst->Integer = src->Integer; + dst->InstanceDivisor = binding->InstanceDivisor; + dst->_ElementSize = src->_ElementSize; + _mesa_reference_buffer_object(ctx, &dst->BufferObj, binding->BufferObj); +} + extern void GLAPIENTRY _mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); @@ -278,6 +317,15 @@ _mesa_copy_client_array(struct gl_context *ctx, struct gl_client_array *dst, struct gl_client_array *src); +extern void +_mesa_copy_vertex_attrib_array(struct gl_context *ctx, + struct gl_vertex_attrib_array *dst, + const struct gl_vertex_attrib_array *src); + +extern void +_mesa_copy_vertex_buffer_binding(struct gl_context *ctx, + struct gl_vertex_buffer_binding *dst, + const struct gl_vertex_buffer_binding *src); extern void _mesa_print_arrays(struct gl_context *ctx);