vertex_attrib_binding(struct gl_context *ctx, GLuint attribIndex,
GLuint bindingIndex)
{
- struct gl_array_object *arrayObj = ctx->Array.VAO;
- struct gl_vertex_attrib_array *array = &arrayObj->VertexAttrib[attribIndex];
+ struct gl_vertex_array_object *vao = ctx->Array.VAO;
+ struct gl_vertex_attrib_array *array = &vao->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;
+ vao->VertexBinding[array->VertexBinding]._BoundArrays &= ~array_bit;
+ vao->VertexBinding[bindingIndex]._BoundArrays |= array_bit;
array->VertexBinding = bindingIndex;
- arrayObj->NewArrays |= array_bit;
+ vao->NewArrays |= array_bit;
}
}
struct gl_buffer_object *vbo,
GLintptr offset, GLsizei stride)
{
- struct gl_array_object *arrayObj = ctx->Array.VAO;
- struct gl_vertex_buffer_binding *binding = &arrayObj->VertexBinding[index];
+ struct gl_vertex_array_object *vao = ctx->Array.VAO;
+ struct gl_vertex_buffer_binding *binding = &vao->VertexBinding[index];
if (binding->BufferObj != vbo ||
binding->Offset != offset ||
binding->Offset = offset;
binding->Stride = stride;
- arrayObj->NewArrays |= binding->_BoundArrays;
+ vao->NewArrays |= binding->_BoundArrays;
}
}
vertex_binding_divisor(struct gl_context *ctx, GLuint bindingIndex,
GLuint divisor)
{
- struct gl_array_object *arrayObj = ctx->Array.VAO;
+ struct gl_vertex_array_object *vao = ctx->Array.VAO;
struct gl_vertex_buffer_binding *binding =
- &arrayObj->VertexBinding[bindingIndex];
+ &vao->VertexBinding[bindingIndex];
if (binding->InstanceDivisor != divisor) {
FLUSH_VERTICES(ctx, _NEW_ARRAY);
binding->InstanceDivisor = divisor;
- arrayObj->NewArrays |= binding->_BoundArrays;
+ vao->NewArrays |= binding->_BoundArrays;
}
}
_mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr)
{
const GLbitfield legalTypes = UNSIGNED_BYTE_BIT;
- /* see table 2.4 edits in GL_EXT_gpu_shader4 spec: */
- const GLboolean integer = GL_TRUE;
+ /* this is the same type that glEdgeFlag uses */
+ const GLboolean integer = GL_FALSE;
GET_CURRENT_CONTEXT(ctx);
FLUSH_VERTICES(ctx, 0);
void GLAPIENTRY
_mesa_EnableVertexAttribArray(GLuint index)
{
- struct gl_array_object *arrayObj;
+ struct gl_vertex_array_object *vao;
GET_CURRENT_CONTEXT(ctx);
if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
return;
}
- arrayObj = ctx->Array.VAO;
+ vao = ctx->Array.VAO;
- ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->_VertexAttrib));
+ ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(vao->_VertexAttrib));
- if (!arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) {
+ if (!vao->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);
+ vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled = GL_TRUE;
+ vao->_Enabled |= VERT_BIT_GENERIC(index);
+ vao->NewArrays |= VERT_BIT_GENERIC(index);
}
}
void GLAPIENTRY
_mesa_DisableVertexAttribArray(GLuint index)
{
- struct gl_array_object *arrayObj;
+ struct gl_vertex_array_object *vao;
GET_CURRENT_CONTEXT(ctx);
if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
return;
}
- arrayObj = ctx->Array.VAO;
+ vao = ctx->Array.VAO;
- ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->_VertexAttrib));
+ ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(vao->_VertexAttrib));
- if (arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) {
+ if (vao->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);
+ vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled = GL_FALSE;
+ vao->_Enabled &= ~VERT_BIT_GENERIC(index);
+ vao->NewArrays |= VERT_BIT_GENERIC(index);
}
}
get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname,
const char *caller)
{
- const struct gl_array_object *arrayObj = ctx->Array.VAO;
+ const struct gl_vertex_array_object *vao = ctx->Array.VAO;
const struct gl_vertex_attrib_array *array;
if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
return 0;
}
- ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->VertexAttrib));
+ ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(vao->VertexAttrib));
- array = &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)];
+ array = &vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)];
switch (pname) {
case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
return array->Enabled;
case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
- return array->Size;
+ return (array->Format == GL_BGRA) ? GL_BGRA : array->Size;
case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
return array->Stride;
case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
return array->Normalized;
case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
- return arrayObj->VertexBinding[array->VertexBinding].BufferObj->Name;
+ return vao->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))
case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB:
if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_instanced_arrays)
|| _mesa_is_gles3(ctx)) {
- return arrayObj->VertexBinding[array->VertexBinding].InstanceDivisor;
+ return vao->VertexBinding[array->VertexBinding].InstanceDivisor;
}
goto error;
case GL_VERTEX_ATTRIB_BINDING:
get_current_attrib(struct gl_context *ctx, GLuint index, const char *function)
{
if (index == 0) {
- /* In OpenGL 3.1 attribute 0 becomes non-magic, just like in OpenGL ES
- * 2.0. Note that we cannot just check for API_OPENGL_CORE here because
- * that will erroneously allow this usage in a 3.0 forward-compatible
- * context too.
- */
- if ((ctx->API != API_OPENGL_CORE || ctx->Version < 31)
- && ctx->API != API_OPENGLES2) {
+ if (_mesa_attr_zero_aliases_vertex(ctx)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(index==0)", function);
return NULL;
}
for (i = 0; i < primcount; i++) {
if (count[i] > 0) {
- CALL_DrawArrays(ctx->Exec, (mode, first[i], count[i]));
+ CALL_DrawArrays(ctx->CurrentDispatch, (mode, first[i], count[i]));
}
}
}
for ( i = 0 ; i < primcount ; i++ ) {
if ( count[i] > 0 ) {
GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
- CALL_DrawArrays(ctx->Exec, ( m, first[i], count[i] ));
+ CALL_DrawArrays(ctx->CurrentDispatch, ( m, first[i], count[i] ));
}
}
}
for ( i = 0 ; i < primcount ; i++ ) {
if ( count[i] > 0 ) {
GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
- CALL_DrawElements(ctx->Exec, ( m, count[i], type, indices[i] ));
+ CALL_DrawElements(ctx->CurrentDispatch, ( m, count[i], type,
+ indices[i] ));
}
}
}
GLsizei stride)
{
GET_CURRENT_CONTEXT(ctx);
- const struct gl_array_object *arrayObj = ctx->Array.VAO;
+ const struct gl_vertex_array_object *vao = ctx->Array.VAO;
struct gl_buffer_object *vbo;
ASSERT_OUTSIDE_BEGIN_END(ctx);
return;
}
- if (buffer == arrayObj->VertexBinding[VERT_ATTRIB_GENERIC(bindingIndex)].BufferObj->Name) {
- vbo = arrayObj->VertexBinding[VERT_ATTRIB_GENERIC(bindingIndex)].BufferObj;
+ if (buffer == vao->VertexBinding[VERT_ATTRIB_GENERIC(bindingIndex)].BufferObj->Name) {
+ vbo = vao->VertexBinding[VERT_ATTRIB_GENERIC(bindingIndex)].BufferObj;
} else if (buffer != 0) {
vbo = _mesa_lookup_bufferobj(ctx, buffer);
}
+void GLAPIENTRY
+_mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
+ const GLintptr *offsets, const GLsizei *strides)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_vertex_array_object * const vao = ctx->Array.VAO;
+ GLuint i;
+
+ 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.VAO == ctx->Array.DefaultVAO) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBindVertexBuffers(No array object bound)");
+ return;
+ }
+
+ /* The ARB_multi_bind spec says:
+ *
+ * "An INVALID_OPERATION error is generated if <first> + <count>
+ * is greater than the value of MAX_VERTEX_ATTRIB_BINDINGS."
+ */
+ if (first + count > ctx->Const.MaxVertexAttribBindings) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBindVertexBuffers(first=%u + count=%d > the value of "
+ "GL_MAX_VERTEX_ATTRIB_BINDINGS=%u)",
+ first, count, ctx->Const.MaxVertexAttribBindings);
+ return;
+ }
+
+ if (!buffers) {
+ /**
+ * The ARB_multi_bind spec says:
+ *
+ * "If <buffers> is NULL, each affected vertex buffer binding point
+ * from <first> through <first>+<count>-1 will be reset to have no
+ * bound buffer object. In this case, the offsets and strides
+ * associated with the binding points are set to default values,
+ * ignoring <offsets> and <strides>."
+ */
+ struct gl_buffer_object *vbo = ctx->Shared->NullBufferObj;
+
+ for (i = 0; i < count; i++)
+ bind_vertex_buffer(ctx, VERT_ATTRIB_GENERIC(first + i), vbo, 0, 16);
+
+ return;
+ }
+
+ /* Note that the error semantics for multi-bind commands differ from
+ * those of other GL commands.
+ *
+ * The Issues section in the ARB_multi_bind spec says:
+ *
+ * "(11) Typically, OpenGL specifies that if an error is generated by
+ * a command, that command has no effect. This is somewhat
+ * unfortunate for multi-bind commands, because it would require
+ * a first pass to scan the entire list of bound objects for
+ * errors and then a second pass to actually perform the
+ * bindings. Should we have different error semantics?
+ *
+ * RESOLVED: Yes. In this specification, when the parameters for
+ * one of the <count> binding points are invalid, that binding
+ * point is not updated and an error will be generated. However,
+ * other binding points in the same command will be updated if
+ * their parameters are valid and no other error occurs."
+ */
+
+ _mesa_begin_bufferobj_lookups(ctx);
+
+ for (i = 0; i < count; i++) {
+ struct gl_buffer_object *vbo;
+
+ /* The ARB_multi_bind spec says:
+ *
+ * "An INVALID_VALUE error is generated if any value in
+ * <offsets> or <strides> is negative (per binding)."
+ */
+ if (offsets[i] < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glBindVertexBuffer(offsets[%u]=%lldd < 0)",
+ i, (long long int) offsets[i]);
+ continue;
+ }
+
+ if (strides[i] < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glBindVertexBuffer(strides[%u]=%lld < 0)",
+ i, (long long int) strides[i]);
+ continue;
+ }
+
+ if (buffers[i]) {
+ struct gl_vertex_buffer_binding *binding =
+ &vao->VertexBinding[VERT_ATTRIB_GENERIC(first + i)];
+
+ if (buffers[i] == binding->BufferObj->Name)
+ vbo = binding->BufferObj;
+ else
+ vbo = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i,
+ "glBindVertexBuffers");
+
+ if (!vbo)
+ continue;
+ } else {
+ vbo = ctx->Shared->NullBufferObj;
+ }
+
+ bind_vertex_buffer(ctx, VERT_ATTRIB_GENERIC(first + i), vbo,
+ offsets[i], strides[i]);
+ }
+
+ _mesa_end_bufferobj_lookups(ctx);
+}
+
+
void GLAPIENTRY
_mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type,
GLboolean normalized, GLuint relativeOffset)
void
_mesa_print_arrays(struct gl_context *ctx)
{
- struct gl_array_object *arrayObj = ctx->Array.VAO;
+ struct gl_vertex_array_object *vao = ctx->Array.VAO;
GLuint i;
- _mesa_update_array_object_max_element(ctx, arrayObj);
+ _mesa_update_vao_max_element(ctx, vao);
- 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]);
+ printf("Array Object %u\n", vao->Name);
+ if (vao->_VertexAttrib[VERT_ATTRIB_POS].Enabled)
+ print_array("Vertex", -1, &vao->_VertexAttrib[VERT_ATTRIB_POS]);
+ if (vao->_VertexAttrib[VERT_ATTRIB_NORMAL].Enabled)
+ print_array("Normal", -1, &vao->_VertexAttrib[VERT_ATTRIB_NORMAL]);
+ if (vao->_VertexAttrib[VERT_ATTRIB_COLOR0].Enabled)
+ print_array("Color", -1, &vao->_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 (vao->_VertexAttrib[VERT_ATTRIB_TEX(i)].Enabled)
+ print_array("TexCoord", i, &vao->_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)]);
- printf(" _MaxElement = %u\n", arrayObj->_MaxElement);
+ if (vao->_VertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
+ print_array("Attrib", i, &vao->_VertexAttrib[VERT_ATTRIB_GENERIC(i)]);
+ printf(" _MaxElement = %u\n", vao->_MaxElement);
}
_mesa_init_varray(struct gl_context *ctx)
{
ctx->Array.DefaultVAO = ctx->Driver.NewArrayObject(ctx, 0);
- _mesa_reference_array_object(ctx, &ctx->Array.VAO,
- ctx->Array.DefaultVAO);
+ _mesa_reference_vao(ctx, &ctx->Array.VAO, ctx->Array.DefaultVAO);
ctx->Array.ActiveTexture = 0; /* GL_ARB_multitexture */
ctx->Array.Objects = _mesa_NewHashTable();
static void
delete_arrayobj_cb(GLuint id, void *data, void *userData)
{
- struct gl_array_object *arrayObj = (struct gl_array_object *) data;
+ struct gl_vertex_array_object *vao = (struct gl_vertex_array_object *) data;
struct gl_context *ctx = (struct gl_context *) userData;
- _mesa_delete_array_object(ctx, arrayObj);
+ _mesa_delete_vao(ctx, vao);
}