mesa: Implement glBindVertexBuffers

v2: Use the user provided offset and stride when the buffer ID is zero.

Reviewed-by: Brian Paul <brianp@vmware.com> (v1)
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com> (v1)
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org> (v2)
This commit is contained in:
Fredrik Höglund 2013-11-15 20:01:07 +01:00
parent f0c36cf4fa
commit 63995b902a
1 changed files with 113 additions and 0 deletions

View File

@ -1443,6 +1443,119 @@ 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);
}