diff options
-rw-r--r-- | src/mesa/main/varray.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c index d7dc2325879..46956efb5a8 100644 --- a/src/mesa/main/varray.c +++ b/src/mesa/main/varray.c @@ -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); } |