diff options
Diffstat (limited to 'mesalib/src/mesa/main')
-rw-r--r-- | mesalib/src/mesa/main/api_arrayelt.c | 43 | ||||
-rw-r--r-- | mesalib/src/mesa/main/arrayobj.c | 73 | ||||
-rw-r--r-- | mesalib/src/mesa/main/arrayobj.h | 5 | ||||
-rw-r--r-- | mesalib/src/mesa/main/attrib.c | 7 | ||||
-rw-r--r-- | mesalib/src/mesa/main/bufferobj.c | 28 | ||||
-rw-r--r-- | mesalib/src/mesa/main/bufferobj.h | 9 | ||||
-rw-r--r-- | mesalib/src/mesa/main/context.c | 6 | ||||
-rw-r--r-- | mesalib/src/mesa/main/dd.h | 9 | ||||
-rw-r--r-- | mesalib/src/mesa/main/enable.c | 2 | ||||
-rw-r--r-- | mesalib/src/mesa/main/extensions.c | 2 | ||||
-rw-r--r-- | mesalib/src/mesa/main/get.c | 30 | ||||
-rw-r--r-- | mesalib/src/mesa/main/get_hash_params.py | 18 | ||||
-rw-r--r-- | mesalib/src/mesa/main/getstring.c | 49 | ||||
-rw-r--r-- | mesalib/src/mesa/main/glformats.c | 5 | ||||
-rw-r--r-- | mesalib/src/mesa/main/mtypes.h | 76 | ||||
-rw-r--r-- | mesalib/src/mesa/main/state.c | 4 | ||||
-rw-r--r-- | mesalib/src/mesa/main/streaming-load-memcpy.c | 85 | ||||
-rw-r--r-- | mesalib/src/mesa/main/streaming-load-memcpy.h | 33 | ||||
-rw-r--r-- | mesalib/src/mesa/main/varray.c | 699 | ||||
-rw-r--r-- | mesalib/src/mesa/main/varray.h | 77 |
20 files changed, 1098 insertions, 162 deletions
diff --git a/mesalib/src/mesa/main/api_arrayelt.c b/mesalib/src/mesa/main/api_arrayelt.c index ea0923837..6822465e8 100644 --- a/mesalib/src/mesa/main/api_arrayelt.c +++ b/mesalib/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,46 +1486,52 @@ _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]; + if (arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled) { + aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR_INDEX]; aa->offset = IndexFuncs[TYPE_IDX(aa->array->Type)]; check_vbo(actx, aa->array->BufferObj); aa++; } - if (arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled) { - aa->array = &arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG]; + if (arrayObj->_VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled) { + aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_EDGEFLAG]; aa->offset = _gloffset_EdgeFlagv; check_vbo(actx, aa->array->BufferObj); aa++; } - if (arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) { - aa->array = &arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL]; + if (arrayObj->_VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) { + aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_NORMAL]; aa->offset = NormalFuncs[TYPE_IDX(aa->array->Type)]; check_vbo(actx, aa->array->BufferObj); aa++; } - if (arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) { - aa->array = &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0]; + if (arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) { + aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR0]; aa->offset = ColorFuncs[aa->array->Size-3][TYPE_IDX(aa->array->Type)]; check_vbo(actx, aa->array->BufferObj); aa++; } - if (arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1].Enabled) { - aa->array = &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1]; + if (arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR1].Enabled) { + aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR1]; aa->offset = SecondaryColorFuncs[TYPE_IDX(aa->array->Type)]; check_vbo(actx, aa->array->BufferObj); aa++; } - if (arrayObj->VertexAttrib[VERT_ATTRIB_FOG].Enabled) { - aa->array = &arrayObj->VertexAttrib[VERT_ATTRIB_FOG]; + if (arrayObj->_VertexAttrib[VERT_ATTRIB_FOG].Enabled) { + aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_FOG]; aa->offset = FogCoordFuncs[TYPE_IDX(aa->array->Type)]; check_vbo(actx, aa->array->BufferObj); aa++; } for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { struct gl_client_array *attribArray = - &arrayObj->VertexAttrib[VERT_ATTRIB_TEX(i)]; + &arrayObj->_VertexAttrib[VERT_ATTRIB_TEX(i)]; if (attribArray->Enabled) { /* NOTE: we use generic glVertexAttribNV functions here. * If we ever remove GL_NV_vertex_program this will have to change. @@ -1543,7 +1550,7 @@ _ae_update_state(struct gl_context *ctx) /* generic vertex attribute arrays */ for (i = 1; i < VERT_ATTRIB_GENERIC_MAX; i++) { /* skip zero! */ struct gl_client_array *attribArray = - &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(i)]; + &arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(i)]; if (attribArray->Enabled) { GLint intOrNorm; at->array = attribArray; @@ -1570,18 +1577,18 @@ _ae_update_state(struct gl_context *ctx) } /* finally, vertex position */ - if (arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC0].Enabled) { + if (arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC0].Enabled) { /* Use glVertex(v) instead of glVertexAttrib(0, v) to be sure it's * issued as the last (provoking) attribute). */ - aa->array = &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC0]; + aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC0]; assert(aa->array->Size >= 2); /* XXX fix someday? */ aa->offset = VertexFuncs[aa->array->Size-2][TYPE_IDX(aa->array->Type)]; check_vbo(actx, aa->array->BufferObj); aa++; } - else if (arrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled) { - aa->array = &arrayObj->VertexAttrib[VERT_ATTRIB_POS]; + else if (arrayObj->_VertexAttrib[VERT_ATTRIB_POS].Enabled) { + aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_POS]; aa->offset = VertexFuncs[aa->array->Size-2][TYPE_IDX(aa->array->Type)]; check_vbo(actx, aa->array->BufferObj); aa++; diff --git a/mesalib/src/mesa/main/arrayobj.c b/mesalib/src/mesa/main/arrayobj.c index 5d50d29f8..dbf8fdc73 100644 --- a/mesalib/src/mesa/main/arrayobj.c +++ b/mesalib/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,8 +81,11 @@ unbind_array_object_vbos(struct gl_context *ctx, struct gl_array_object *obj) { GLuint i; - for (i = 0; i < Elements(obj->VertexAttrib); i++) - _mesa_reference_buffer_object(ctx, &obj->VertexAttrib[i].BufferObj, NULL); + 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); } @@ -215,31 +228,31 @@ _mesa_initialize_array_object( struct gl_context *ctx, obj->RefCount = 1; /* Init the individual arrays */ - for (i = 0; i < Elements(obj->VertexAttrib); i++) { + 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; } } @@ -279,7 +292,7 @@ remove_array_object( struct gl_context *ctx, struct gl_array_object *obj ) /** * Helper for _mesa_update_array_object_max_element(). - * \return min(arrayObj->VertexAttrib[*]._MaxElement). + * \return min(arrayObj->_VertexAttrib[*]._MaxElement). */ static GLuint compute_max_element(struct gl_array_object *arrayObj, GLbitfield64 enabled) @@ -291,7 +304,7 @@ compute_max_element(struct gl_array_object *arrayObj, GLbitfield64 enabled) GLint attrib = ffsll(enabled) - 1; enabled ^= BITFIELD64_BIT(attrib); - client_array = &arrayObj->VertexAttrib[attrib]; + client_array = &arrayObj->_VertexAttrib[attrib]; assert(client_array->Enabled); _mesa_update_array_max_element(client_array); min = MIN2(min, client_array->_MaxElement); @@ -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/mesalib/src/mesa/main/arrayobj.h b/mesalib/src/mesa/main/arrayobj.h index 492ef3501..7c3720242 100644 --- a/mesalib/src/mesa/main/arrayobj.h +++ b/mesalib/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/mesalib/src/mesa/main/attrib.c b/mesalib/src/mesa/main/attrib.c index ca617f744..c9332bd52 100644 --- a/mesalib/src/mesa/main/attrib.c +++ b/mesalib/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++) - _mesa_copy_client_array(ctx, &dest->VertexAttrib[i], &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/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c index f8312bbb4..351934433 100644 --- a/mesalib/src/mesa/main/bufferobj.c +++ b/mesalib/src/mesa/main/bufferobj.c @@ -655,16 +655,17 @@ _mesa_free_buffer_objects( struct gl_context *ctx ) } } -static bool -handle_bind_buffer_gen(struct gl_context *ctx, - GLenum target, - GLuint buffer, - struct gl_buffer_object **buf_handle) +bool +_mesa_handle_bind_buffer_gen(struct gl_context *ctx, + GLenum target, + GLuint buffer, + struct gl_buffer_object **buf_handle, + const char *caller) { struct gl_buffer_object *buf = *buf_handle; if (!buf && ctx->API == API_OPENGL_CORE) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glBindBuffer(non-gen name)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-gen name)", caller); return false; } @@ -675,7 +676,7 @@ handle_bind_buffer_gen(struct gl_context *ctx, ASSERT(ctx->Driver.NewBufferObject); buf = ctx->Driver.NewBufferObject(ctx, buffer, target); if (!buf) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindBufferARB"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller); return false; } _mesa_HashInsert(ctx->Shared->BufferObjects, buffer, buf); @@ -719,7 +720,8 @@ bind_buffer_object(struct gl_context *ctx, GLenum target, GLuint buffer) else { /* non-default buffer object */ newBufObj = _mesa_lookup_bufferobj(ctx, buffer); - if (!handle_bind_buffer_gen(ctx, target, buffer, &newBufObj)) + if (!_mesa_handle_bind_buffer_gen(ctx, target, buffer, + &newBufObj, "glBindBuffer")) return; } @@ -862,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) { @@ -2181,7 +2183,8 @@ _mesa_BindBufferRange(GLenum target, GLuint index, } else { bufObj = _mesa_lookup_bufferobj(ctx, buffer); } - if (!handle_bind_buffer_gen(ctx, target, buffer, &bufObj)) + if (!_mesa_handle_bind_buffer_gen(ctx, target, buffer, + &bufObj, "glBindBufferRange")) return; if (!bufObj) { @@ -2227,7 +2230,8 @@ _mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer) } else { bufObj = _mesa_lookup_bufferobj(ctx, buffer); } - if (!handle_bind_buffer_gen(ctx, target, buffer, &bufObj)) + if (!_mesa_handle_bind_buffer_gen(ctx, target, buffer, + &bufObj, "glBindBufferBase")) return; if (!bufObj) { diff --git a/mesalib/src/mesa/main/bufferobj.h b/mesalib/src/mesa/main/bufferobj.h index 9b582f8c1..0b898a21b 100644 --- a/mesalib/src/mesa/main/bufferobj.h +++ b/mesalib/src/mesa/main/bufferobj.h @@ -28,7 +28,7 @@ #ifndef BUFFEROBJ_H #define BUFFEROBJ_H - +#include <stdbool.h> #include "mtypes.h" @@ -62,6 +62,13 @@ _mesa_init_buffer_objects( struct gl_context *ctx ); extern void _mesa_free_buffer_objects( struct gl_context *ctx ); +extern bool +_mesa_handle_bind_buffer_gen(struct gl_context *ctx, + GLenum target, + GLuint buffer, + struct gl_buffer_object **buf_handle, + const char *caller); + extern void _mesa_update_default_objects_buffer_objects(struct gl_context *ctx); diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c index 6cdeed19b..d005d2370 100644 --- a/mesalib/src/mesa/main/context.c +++ b/mesalib/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; } @@ -804,7 +808,7 @@ init_attrib_groups(struct gl_context *ctx) ctx->NewState = _NEW_ALL; ctx->NewDriverState = ~0; ctx->ErrorValue = GL_NO_ERROR; - ctx->ResetStatus = GL_NO_ERROR; + ctx->ShareGroupReset = false; ctx->varying_vp_inputs = VERT_BIT_ALL; return GL_TRUE; diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h index d7c432713..b5b874f47 100644 --- a/mesalib/src/mesa/main/dd.h +++ b/mesalib/src/mesa/main/dd.h @@ -890,6 +890,15 @@ struct dd_function_table { struct gl_texture_object *texObj, struct gl_texture_image *texImage, const GLvoid *vdpSurface, GLuint index); + + /** + * Query reset status for GL_ARB_robustness + * + * Per \c glGetGraphicsResetStatusARB, this function should return a + * non-zero value once after a reset. If a reset is non-atomic, the + * non-zero status should be returned for the duration of the reset. + */ + GLenum (*GetGraphicsResetStatus)(struct gl_context *ctx); }; diff --git a/mesalib/src/mesa/main/enable.c b/mesalib/src/mesa/main/enable.c index dd6a772f9..c047f5df2 100644 --- a/mesalib/src/mesa/main/enable.c +++ b/mesalib/src/mesa/main/enable.c @@ -135,6 +135,8 @@ client_state(struct gl_context *ctx, GLenum cap, GLboolean state) else arrayObj->_Enabled &= ~flag; + arrayObj->NewArrays |= flag; + if (ctx->Driver.Enable) { ctx->Driver.Enable( ctx, cap, state ); } diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index 48c4e9f1b..104618c23 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -165,9 +165,11 @@ static const struct extension extension_table[] = { { "GL_ARB_uniform_buffer_object", o(ARB_uniform_buffer_object), GL, 2009 }, { "GL_ARB_vertex_array_bgra", o(EXT_vertex_array_bgra), GL, 2008 }, { "GL_ARB_vertex_array_object", o(dummy_true), GL, 2006 }, + { "GL_ARB_vertex_attrib_binding", o(dummy_true), GL, 2012 }, { "GL_ARB_vertex_buffer_object", o(dummy_true), GLL, 2003 }, { "GL_ARB_vertex_program", o(ARB_vertex_program), GLL, 2002 }, { "GL_ARB_vertex_shader", o(ARB_vertex_shader), GL, 2002 }, + { "GL_ARB_vertex_type_10f_11f_11f_rev", o(ARB_vertex_type_10f_11f_11f_rev), GL, 2013 }, { "GL_ARB_vertex_type_2_10_10_10_rev", o(ARB_vertex_type_2_10_10_10_rev), GL, 2009 }, { "GL_ARB_window_pos", o(dummy_true), GLL, 2001 }, /* EXT extensions */ diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c index 6a0de0c16..eee855007 100644 --- a/mesalib/src/mesa/main/get.c +++ b/mesalib/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) { @@ -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: @@ -1740,6 +1740,30 @@ find_value_indexed(const char *func, GLenum pname, GLuint index, union value *v) goto invalid_value; v->value_int64 = ctx->AtomicBufferBindings[index].Size; return TYPE_INT64; + + case GL_VERTEX_BINDING_DIVISOR: + if (!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_instanced_arrays) + goto invalid_enum; + if (index >= ctx->Const.VertexProgram.MaxAttribs) + goto invalid_value; + v->value_int = ctx->Array.ArrayObj->VertexBinding[VERT_ATTRIB_GENERIC(index)].InstanceDivisor; + return TYPE_INT; + + case GL_VERTEX_BINDING_OFFSET: + if (!_mesa_is_desktop_gl(ctx)) + goto invalid_enum; + if (index >= ctx->Const.VertexProgram.MaxAttribs) + goto invalid_value; + v->value_int = ctx->Array.ArrayObj->VertexBinding[VERT_ATTRIB_GENERIC(index)].Offset; + return TYPE_INT; + + case GL_VERTEX_BINDING_STRIDE: + if (!_mesa_is_desktop_gl(ctx)) + goto invalid_enum; + if (index >= ctx->Const.VertexProgram.MaxAttribs) + goto invalid_value; + v->value_int = ctx->Array.ArrayObj->VertexBinding[VERT_ATTRIB_GENERIC(index)].Stride; + return TYPE_INT; } invalid_enum: diff --git a/mesalib/src/mesa/main/get_hash_params.py b/mesalib/src/mesa/main/get_hash_params.py index 0851b7b70..c961feeee 100644 --- a/mesalib/src/mesa/main/get_hash_params.py +++ b/mesalib/src/mesa/main/get_hash_params.py @@ -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 @@ -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 @@ -737,6 +737,10 @@ descriptor=[ [ "MAX_GEOMETRY_ATOMIC_COUNTERS", "CONTEXT_INT(Const.GeometryProgram.MaxAtomicCounters), extra_ARB_shader_atomic_counters_and_geometry_shader" ], [ "MAX_COMBINED_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.MaxCombinedAtomicBuffers), extra_ARB_shader_atomic_counters" ], [ "MAX_COMBINED_ATOMIC_COUNTERS", "CONTEXT_INT(Const.MaxCombinedAtomicCounters), extra_ARB_shader_atomic_counters" ], + +# GL_ARB_vertex_attrib_binding + [ "MAX_VERTEX_ATTRIB_RELATIVE_OFFSET", "CONTEXT_ENUM(Const.MaxVertexAttribRelativeOffset), NO_EXTRA" ], + [ "MAX_VERTEX_ATTRIB_BINDINGS", "CONTEXT_ENUM(Const.MaxVertexAttribBindings), NO_EXTRA" ], ]}, # Enums restricted to OpenGL Core profile diff --git a/mesalib/src/mesa/main/getstring.c b/mesalib/src/mesa/main/getstring.c index 0e075427f..d8189115a 100644 --- a/mesalib/src/mesa/main/getstring.c +++ b/mesalib/src/mesa/main/getstring.c @@ -23,7 +23,7 @@ */ - +#include <stdbool.h> #include "glheader.h" #include "context.h" #include "get.h" @@ -305,11 +305,50 @@ GLenum GLAPIENTRY _mesa_GetGraphicsResetStatusARB( void ) { GET_CURRENT_CONTEXT(ctx); - GLenum status = ctx->ResetStatus; + GLenum status = GL_NO_ERROR; + + /* The ARB_robustness specification says: + * + * "If the reset notification behavior is NO_RESET_NOTIFICATION_ARB, + * then the implementation will never deliver notification of reset + * events, and GetGraphicsResetStatusARB will always return NO_ERROR." + */ + if (ctx->Const.ResetStrategy == GL_NO_RESET_NOTIFICATION_ARB) { + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, + "glGetGraphicsResetStatusARB always returns GL_NO_ERROR " + "because reset notifictation was not requested at context " + "creation.\n"); + + return GL_NO_ERROR; + } - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glGetGraphicsResetStatusARB" - "(always returns GL_NO_ERROR)\n"); + if (ctx->Driver.GetGraphicsResetStatus) { + /* Query the reset status of this context from the driver core. + */ + status = ctx->Driver.GetGraphicsResetStatus(ctx); + + _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + + /* If this context has not been affected by a GPU reset, check to see if + * some other context in the share group has been affected by a reset. + * If another context saw a reset but this context did not, assume that + * this context was not guilty. + */ + if (status != GL_NO_ERROR) { + ctx->Shared->ShareGroupReset = true; + } else if (ctx->Shared->ShareGroupReset && !ctx->ShareGroupReset) { + status = GL_INNOCENT_CONTEXT_RESET_ARB; + } + + ctx->ShareGroupReset = ctx->Shared->ShareGroupReset; + _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + } + + if (!ctx->Driver.GetGraphicsResetStatus && (MESA_VERBOSE & VERBOSE_API)) + _mesa_debug(ctx, + "glGetGraphicsResetStatusARB always returns GL_NO_ERROR " + "because the driver doesn't track reset status.\n"); return status; } diff --git a/mesalib/src/mesa/main/glformats.c b/mesalib/src/mesa/main/glformats.c index dfee6f196..740faa890 100644 --- a/mesalib/src/mesa/main/glformats.c +++ b/mesalib/src/mesa/main/glformats.c @@ -345,6 +345,11 @@ _mesa_bytes_per_vertex_attrib(GLint comps, GLenum type) return sizeof(GLuint); else return -1; + case GL_UNSIGNED_INT_10F_11F_11F_REV: + if (comps == 3) + return sizeof(GLuint); + else + return -1; default: return -1; } diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index b5c5583d6..ae96e2326 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -35,6 +35,7 @@ #include <stdint.h> /* uint32_t */ +#include <stdbool.h> #include "main/glheader.h" #include "main/config.h" @@ -1474,6 +1475,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,12 +1546,21 @@ struct gl_array_object */ GLboolean EverBound; + /** Derived vertex attribute arrays */ + struct gl_client_array _VertexAttrib[VERT_ATTRIB_MAX]; + /** Vertex attribute arrays */ - struct gl_client_array VertexAttrib[VERT_ATTRIB_MAX]; + 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; + /** Mask of VERT_BIT_* values indicating changed/dirty arrays */ + GLbitfield64 NewArrays; + /** * Min of all enabled arrays' _MaxElement. When arrays reside inside VBOs * we can determine the max legal (in bounds) glDrawElements array index. @@ -2765,6 +2813,17 @@ struct gl_shared_state /** GL_ARB_sampler_objects */ struct _mesa_HashTable *SamplerObjects; + + /** + * Some context in this share group was affected by a GPU reset + * + * On the next call to \c glGetGraphicsResetStatus, contexts that have not + * been affected by a GPU reset must also return + * \c GL_INNOCENT_CONTEXT_RESET_ARB. + * + * Once this field becomes true, it is never reset to false. + */ + bool ShareGroupReset; }; @@ -3213,6 +3272,10 @@ struct gl_constants GLuint MaxAtomicBufferSize; GLuint MaxCombinedAtomicBuffers; GLuint MaxCombinedAtomicCounters; + + /** GL_ARB_vertex_attrib_binding */ + GLint MaxVertexAttribRelativeOffset; + GLint MaxVertexAttribBindings; }; @@ -3291,6 +3354,7 @@ struct gl_extensions GLboolean ARB_uniform_buffer_object; GLboolean ARB_vertex_program; GLboolean ARB_vertex_shader; + GLboolean ARB_vertex_type_10f_11f_11f_rev; GLboolean ARB_vertex_type_2_10_10_10_rev; GLboolean EXT_blend_color; GLboolean EXT_blend_equation_separate; @@ -3851,9 +3915,6 @@ struct gl_context GLenum ErrorValue; /**< Last error code */ - /* GL_ARB_robustness */ - GLenum ResetStatus; - /** * Recognize and silence repeated error debug messages in buggy apps. */ @@ -3918,6 +3979,13 @@ struct gl_context const void *vdpGetProcAddress; struct set *vdpSurfaces; /*@}*/ + + /** + * Has this context observed a GPU reset in any context in the share group? + * + * Once this field becomes true, it is never reset to false. + */ + GLboolean ShareGroupReset; }; diff --git a/mesalib/src/mesa/main/state.c b/mesalib/src/mesa/main/state.c index 23926410b..33070b7e0 100644 --- a/mesalib/src/mesa/main/state.c +++ b/mesalib/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); @@ -430,6 +433,7 @@ _mesa_update_state_locked( struct gl_context *ctx ) new_state = ctx->NewState | new_prog_state; ctx->NewState = 0; ctx->Driver.UpdateState(ctx, new_state); + ctx->Array.ArrayObj->NewArrays = 0x0; } diff --git a/mesalib/src/mesa/main/streaming-load-memcpy.c b/mesalib/src/mesa/main/streaming-load-memcpy.c new file mode 100644 index 000000000..d7147afdc --- /dev/null +++ b/mesalib/src/mesa/main/streaming-load-memcpy.c @@ -0,0 +1,85 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * Matt Turner <mattst88@gmail.com> + * + */ + +#include "main/macros.h" +#include "main/streaming-load-memcpy.h" +#include <smmintrin.h> + +/* Copies memory from src to dst, using SSE 4.1's MOVNTDQA to get streaming + * read performance from uncached memory. + */ +void +_mesa_streaming_load_memcpy(void *restrict dst, void *restrict src, size_t len) +{ + char *restrict d = dst; + char *restrict s = src; + + /* If dst and src are not co-aligned, fallback to memcpy(). */ + if (((uintptr_t)d & 15) != ((uintptr_t)s & 15)) { + memcpy(d, s, len); + return; + } + + /* memcpy() the misaligned header. At the end of this if block, <d> and <s> + * are aligned to a 16-byte boundary or <len> == 0. + */ + if ((uintptr_t)d & 15) { + uintptr_t bytes_before_alignment_boundary = 16 - ((uintptr_t)d & 15); + assert(bytes_before_alignment_boundary < 16); + + memcpy(d, s, MIN2(bytes_before_alignment_boundary, len)); + + d = (char *)ALIGN((uintptr_t)d, 16); + s = (char *)ALIGN((uintptr_t)s, 16); + len -= MIN2(bytes_before_alignment_boundary, len); + } + + while (len >= 64) { + __m128i *dst_cacheline = (__m128i *)d; + __m128i *src_cacheline = (__m128i *)s; + + __m128i temp1 = _mm_stream_load_si128(src_cacheline + 0); + __m128i temp2 = _mm_stream_load_si128(src_cacheline + 1); + __m128i temp3 = _mm_stream_load_si128(src_cacheline + 2); + __m128i temp4 = _mm_stream_load_si128(src_cacheline + 3); + + _mm_store_si128(dst_cacheline + 0, temp1); + _mm_store_si128(dst_cacheline + 1, temp2); + _mm_store_si128(dst_cacheline + 2, temp3); + _mm_store_si128(dst_cacheline + 3, temp4); + + d += 64; + s += 64; + len -= 64; + } + + /* memcpy() the tail. */ + if (len) { + memcpy(d, s, len); + } +} diff --git a/mesalib/src/mesa/main/streaming-load-memcpy.h b/mesalib/src/mesa/main/streaming-load-memcpy.h new file mode 100644 index 000000000..41eeeeca0 --- /dev/null +++ b/mesalib/src/mesa/main/streaming-load-memcpy.h @@ -0,0 +1,33 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * Matt Turner <mattst88@gmail.com> + * + */ + +/* Copies memory from src to dst, using SSE 4.1's MOVNTDQA to get streaming + * read performance from uncached memory. + */ +void +_mesa_streaming_load_memcpy(void *restrict dst, void *restrict src, size_t len); diff --git a/mesalib/src/mesa/main/varray.c b/mesalib/src/mesa/main/varray.c index dee476abb..d17d698d3 100644 --- a/mesalib/src/mesa/main/varray.c +++ b/mesalib/src/mesa/main/varray.c @@ -60,6 +60,7 @@ #define FIXED_GL_BIT 0x800 #define UNSIGNED_INT_2_10_10_10_REV_BIT 0x1000 #define INT_2_10_10_10_REV_BIT 0x2000 +#define UNSIGNED_INT_10F_11F_11F_REV_BIT 0x4000 /** Convert GL datatype enum into a <type>_BIT value seen above */ @@ -96,6 +97,8 @@ type_to_bit(const struct gl_context *ctx, GLenum type) return UNSIGNED_INT_2_10_10_10_REV_BIT; case GL_INT_2_10_10_10_REV: return INT_2_10_10_10_REV_BIT; + case GL_UNSIGNED_INT_10F_11F_11F_REV: + return UNSIGNED_INT_10F_11F_11F_REV_BIT; default: return 0; } @@ -103,54 +106,110 @@ type_to_bit(const struct gl_context *ctx, GLenum type) /** - * Do error checking and update state for glVertex/Color/TexCoord/...Pointer - * functions. - * - * \param func name of calling function used for error reporting - * \param attrib the attribute array index to update - * \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 stride stride between elements, in elements - * \param normalized are integer types converted to floats in [-1, 1]? - * \param integer integer-valued values (will not be normalized to [-1,1]) - * \param ptr the address (or offset inside VBO) of the array data + * Sets the VertexBinding field in the vertex attribute given by attribIndex. */ static void -update_array(struct gl_context *ctx, - const char *func, - GLuint attrib, GLbitfield legalTypesMask, - GLint sizeMin, GLint sizeMax, - GLint size, GLenum type, GLsizei stride, - GLboolean normalized, GLboolean integer, - const GLvoid *ptr) +vertex_attrib_binding(struct gl_context *ctx, GLuint attribIndex, + GLuint bindingIndex) { - struct gl_client_array *array; - GLbitfield typeBit; - GLsizei elementSize; - GLenum format = GL_RGBA; + struct gl_array_object *arrayObj = ctx->Array.ArrayObj; + struct gl_vertex_attrib_array *array = &arrayObj->VertexAttrib[attribIndex]; - /* Page 407 (page 423 of the PDF) of the OpenGL 3.0 spec says: - * - * "Client vertex arrays - all vertex array attribute pointers must - * refer to buffer objects (section 2.9.2). The default vertex array - * object (the name zero) is also deprecated. Calling - * VertexAttribPointer when no buffer object or no vertex array object - * is bound will generate an INVALID_OPERATION error..." - * - * The check for VBOs is handled below. - */ - if (ctx->API == API_OPENGL_CORE - && (ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no array object bound)", - func); - return; + 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() 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 relativeOffset Offset of the first element relative to the binding offset. + */ +static bool +update_array_format(struct gl_context *ctx, + const char *func, + GLuint attrib, GLbitfield legalTypesMask, + GLint sizeMin, GLint sizeMax, + GLint size, GLenum type, + GLboolean normalized, GLboolean integer, + GLuint relativeOffset) +{ + struct gl_vertex_attrib_array *array; + GLbitfield typeBit; + GLuint elementSize; + GLenum format = GL_RGBA; if (_mesa_is_gles(ctx)) { - legalTypesMask &= ~(FIXED_GL_BIT | DOUBLE_BIT); + legalTypesMask &= ~(FIXED_GL_BIT | DOUBLE_BIT | UNSIGNED_INT_10F_11F_11F_REV_BIT); /* GL_INT and GL_UNSIGNED_INT data is not allowed in OpenGL ES until * 3.0. The 2_10_10_10 types are added in OpenGL ES 3.0 or @@ -180,13 +239,16 @@ update_array(struct gl_context *ctx, if (!ctx->Extensions.ARB_vertex_type_2_10_10_10_rev) legalTypesMask &= ~(UNSIGNED_INT_2_10_10_10_REV_BIT | INT_2_10_10_10_REV_BIT); + + if (!ctx->Extensions.ARB_vertex_type_10f_11f_11f_rev) + legalTypesMask &= ~UNSIGNED_INT_10F_11F_11F_REV_BIT; } typeBit = type_to_bit(ctx, type); if (typeBit == 0x0 || (typeBit & legalTypesMask) == 0x0) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(type = %s)", func, _mesa_lookup_enum_by_nr(type)); - return; + return false; } /* Do size parameter checking. @@ -206,26 +268,26 @@ update_array(struct gl_context *ctx, * ... * • size is BGRA and normalized is FALSE;" */ - GLboolean bgra_error = GL_FALSE; + bool bgra_error = false; if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev) { if (type != GL_UNSIGNED_INT_2_10_10_10_REV && type != GL_INT_2_10_10_10_REV && type != GL_UNSIGNED_BYTE) - bgra_error = GL_TRUE; + bgra_error = true; } else if (type != GL_UNSIGNED_BYTE) - bgra_error = GL_TRUE; + bgra_error = true; if (bgra_error) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=GL_BGRA and type=%s)", func, _mesa_lookup_enum_by_nr(type)); - return; + return false; } if (!normalized) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=GL_BGRA and normalized=GL_FALSE)", func); - return; + return false; } format = GL_BGRA; @@ -233,18 +295,106 @@ update_array(struct gl_context *ctx, } else if (size < sizeMin || size > sizeMax || size > 4) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d)", func, size); - return; + return false; } if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev && (type == GL_UNSIGNED_INT_2_10_10_10_REV || type == GL_INT_2_10_10_10_REV) && size != 4) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=%d)", func, size); - return; + return false; + } + + /* The ARB_vertex_attrib_binding_spec says: + * + * An INVALID_VALUE error is generated if <relativeoffset> 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 false; + } + + if (ctx->Extensions.ARB_vertex_type_10f_11f_11f_rev && + type == GL_UNSIGNED_INT_10F_11F_11F_REV && size != 3) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=%d)", func, size); + return false; } ASSERT(size <= 4); + elementSize = _mesa_bytes_per_vertex_attrib(size, type); + assert(elementSize != -1); + + 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; +} + + +/** + * Do error checking and update state for glVertex/Color/TexCoord/...Pointer + * functions. + * + * \param func name of calling function used for error reporting + * \param attrib the attribute array index to update + * \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 stride stride between elements, in elements + * \param normalized are integer types converted to floats in [-1, 1]? + * \param integer integer-valued values (will not be normalized to [-1,1]) + * \param ptr the address (or offset inside VBO) of the array data + */ +static void +update_array(struct gl_context *ctx, + const char *func, + GLuint attrib, GLbitfield legalTypesMask, + GLint sizeMin, GLint sizeMax, + GLint size, GLenum type, GLsizei stride, + GLboolean normalized, GLboolean integer, + const GLvoid *ptr) +{ + struct gl_vertex_attrib_array *array; + GLsizei effectiveStride; + + /* Page 407 (page 423 of the PDF) of the OpenGL 3.0 spec says: + * + * "Client vertex arrays - all vertex array attribute pointers must + * refer to buffer objects (section 2.9.2). The default vertex array + * object (the name zero) is also deprecated. Calling + * VertexAttribPointer when no buffer object or no vertex array object + * is bound will generate an INVALID_OPERATION error..." + * + * The check for VBOs is handled below. + */ + if (ctx->API == API_OPENGL_CORE + && (ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no array object bound)", + func); + return; + } + + if (!update_array_format(ctx, func, attrib, legalTypesMask, sizeMin, sizeMax, + size, type, normalized, integer, 0)) { + return; + } + if (stride < 0) { _mesa_error( ctx, GL_INVALID_VALUE, "%s(stride=%d)", func, stride ); return; @@ -268,24 +418,18 @@ update_array(struct gl_context *ctx, return; } - elementSize = _mesa_bytes_per_vertex_attrib(size, type); - assert(elementSize != -1); + /* Reset the vertex attrib binding */ + vertex_attrib_binding(ctx, attrib, attrib); + /* The Stride and Ptr fields are not set by update_array_format() */ array = &ctx->Array.ArrayObj->VertexAttrib[attrib]; - array->Size = size; - array->Type = type; - array->Format = format; array->Stride = stride; - array->StrideB = stride ? stride : elementSize; - array->Normalized = normalized; - array->Integer = integer; - array->Ptr = (const GLubyte *) ptr; - array->_ElementSize = elementSize; + array->Ptr = (const GLvoid *) ptr; - _mesa_reference_buffer_object(ctx, &array->BufferObj, - ctx->Array.ArrayBufferObj); - - ctx->NewState |= _NEW_ARRAY; + /* Update the vertex buffer binding */ + effectiveStride = stride != 0 ? stride : array->_ElementSize; + bind_vertex_buffer(ctx, attrib, ctx->Array.ArrayBufferObj, + (GLintptr) ptr, effectiveStride); } @@ -473,7 +617,8 @@ _mesa_VertexAttribPointer(GLuint index, GLint size, GLenum type, HALF_BIT | FLOAT_BIT | DOUBLE_BIT | FIXED_ES_BIT | FIXED_GL_BIT | UNSIGNED_INT_2_10_10_10_REV_BIT | - INT_2_10_10_10_REV_BIT); + INT_2_10_10_10_REV_BIT | + UNSIGNED_INT_10F_11F_11F_REV_BIT); GET_CURRENT_CONTEXT(ctx); if (index >= ctx->Const.VertexProgram.MaxAttribs) { @@ -530,13 +675,14 @@ _mesa_EnableVertexAttribArray(GLuint index) arrayObj = ctx->Array.ArrayObj; - ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->VertexAttrib)); + ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->_VertexAttrib)); 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->_Enabled |= VERT_BIT_GENERIC(index); + arrayObj->NewArrays |= VERT_BIT_GENERIC(index); } } @@ -555,13 +701,14 @@ _mesa_DisableVertexAttribArray(GLuint index) arrayObj = ctx->Array.ArrayObj; - ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->VertexAttrib)); + ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->_VertexAttrib)); 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->_Enabled &= ~VERT_BIT_GENERIC(index); + arrayObj->NewArrays |= VERT_BIT_GENERIC(index); } } @@ -575,16 +722,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: @@ -598,7 +746,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)) @@ -609,7 +757,17 @@ 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; + case GL_VERTEX_ATTRIB_BINDING: + if (_mesa_is_desktop_gl(ctx)) { + return array->VertexBinding - VERT_ATTRIB_GENERIC0; + } + goto error; + case GL_VERTEX_ATTRIB_RELATIVE_OFFSET: + if (_mesa_is_desktop_gl(ctx)) { + return array->RelativeOffset; } goto error; default: @@ -643,7 +801,7 @@ get_current_attrib(struct gl_context *ctx, GLuint index, const char *function) return NULL; } - ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->VertexAttrib)); + ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->_VertexAttrib)); FLUSH_CURRENT(ctx, 0); return ctx->Current.Attrib[VERT_ATTRIB_GENERIC(index)]; @@ -765,7 +923,7 @@ _mesa_GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid **pointer) return; } - ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->VertexAttrib)); + ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->_VertexAttrib)); *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Ptr; } @@ -1141,9 +1299,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; @@ -1155,13 +1314,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; - } + /* 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); } @@ -1191,6 +1358,329 @@ _mesa_primitive_restart_index(const struct gl_context *ctx, GLenum ib_type) /** + * GL_ARB_vertex_attrib_binding + */ +void GLAPIENTRY +_mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset, + GLsizei stride) +{ + GET_CURRENT_CONTEXT(ctx); + const struct gl_array_object *arrayObj = ctx->Array.ArrayObj; + struct gl_buffer_object *vbo; + + 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 <bindingindex> 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 <stride> or <offset> + * 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 == arrayObj->VertexBinding[VERT_ATTRIB_GENERIC(bindingIndex)].BufferObj->Name) { + vbo = arrayObj->VertexBinding[VERT_ATTRIB_GENERIC(bindingIndex)].BufferObj; + } else 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 <buffer> 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); +} + + +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 | + UNSIGNED_INT_10F_11F_11F_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); +} + + +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); +} + + +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 <attribindex> 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: + * + * "<attribindex> must be less than the value of MAX_VERTEX_ATTRIBS and + * <bindingindex> 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 <bindingindex> 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); +} + + +/** * Copy one client vertex array to another. */ void @@ -1213,7 +1703,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. @@ -1245,18 +1764,18 @@ _mesa_print_arrays(struct gl_context *ctx) _mesa_update_array_object_max_element(ctx, arrayObj); printf("Array Object %u\n", arrayObj->Name); - if (arrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled) - print_array("Vertex", -1, &arrayObj->VertexAttrib[VERT_ATTRIB_POS]); - if (arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) - print_array("Normal", -1, &arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL]); - if (arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) - print_array("Color", -1, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0]); + if (arrayObj->_VertexAttrib[VERT_ATTRIB_POS].Enabled) + print_array("Vertex", -1, &arrayObj->_VertexAttrib[VERT_ATTRIB_POS]); + if (arrayObj->_VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) + print_array("Normal", -1, &arrayObj->_VertexAttrib[VERT_ATTRIB_NORMAL]); + if (arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) + print_array("Color", -1, &arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR0]); for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) - if (arrayObj->VertexAttrib[VERT_ATTRIB_TEX(i)].Enabled) - print_array("TexCoord", i, &arrayObj->VertexAttrib[VERT_ATTRIB_TEX(i)]); + if (arrayObj->_VertexAttrib[VERT_ATTRIB_TEX(i)].Enabled) + print_array("TexCoord", i, &arrayObj->_VertexAttrib[VERT_ATTRIB_TEX(i)]); for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) - if (arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled) - print_array("Attrib", i, &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(i)]); + if (arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled) + print_array("Attrib", i, &arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(i)]); printf(" _MaxElement = %u\n", arrayObj->_MaxElement); } diff --git a/mesalib/src/mesa/main/varray.h b/mesalib/src/mesa/main/varray.h index 7e611e8c7..8a9487c6e 100644 --- a/mesalib/src/mesa/main/varray.h +++ b/mesalib/src/mesa/main/varray.h @@ -29,6 +29,7 @@ #include "glheader.h" +#include "bufferobj.h" struct gl_client_array; struct gl_context; @@ -50,8 +51,10 @@ _mesa_update_array_max_element(struct gl_client_array *array) GLsizeiptrARB bufSize = (GLsizeiptrARB) array->BufferObj->Size; if (offset < bufSize) { - array->_MaxElement = (bufSize - offset + array->StrideB - - array->_ElementSize) / array->StrideB; + const GLuint stride = array->StrideB ? + array->StrideB : array->_ElementSize; + array->_MaxElement = (bufSize - offset + stride + - array->_ElementSize) / stride; } else { array->_MaxElement = 0; @@ -64,6 +67,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); @@ -250,11 +291,43 @@ _mesa_VertexAttribDivisor(GLuint index, GLuint divisor); extern unsigned _mesa_primitive_restart_index(const struct gl_context *ctx, GLenum ib_type); +extern void GLAPIENTRY +_mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset, + GLsizei stride); + +extern void GLAPIENTRY +_mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type, + GLboolean normalized, GLuint relativeOffset); + +extern void GLAPIENTRY +_mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type, + GLuint relativeOffset); + +extern void GLAPIENTRY +_mesa_VertexAttribLFormat(GLuint attribIndex, GLint size, GLenum type, + GLuint relativeOffset); + +extern void GLAPIENTRY +_mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex); + +extern void GLAPIENTRY +_mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor); + + extern void _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); |