ES31: Implement Vertex Attrib Binding entry points

This patch intends to implement all entry points related to Vertex
Attrib Binding.

(1) Add entry points and validation code on following APIs:
   - VertexAttribFormat
   - VertexAttribIFormat
   - VertexAttribBinding
   - BindVertexBuffer
   - VertexBindingDivisor
(2) Add queries on following parameters:
   - VERTEX_ATTRIB_BINDING
   - VERTEX_ATTRIB_RELATIVE_OFFSET
   - VERTEX_BINDING_DIVISOR
   - VERTEX_BINDING_OFFSET
   - VERTEX_BINDING_STRIDE
   - VERTEX_BINDING_BUFFER

BUG=angleproject:1593

TEST=angle_end2end_tests
TEST=angle_unittests
TEST=dEQP-GLES31.functional.state_query.integer.max_vertex_attrib_relative_offset_*
TEST=dEQP-GLES31.functional.state_query.integer.max_vertex_attrib_bindings_*
TEST=dEQP-GLES31.functional.state_query.integer.max_vertex_attrib_stride_*
TEST=dEQP-GLES31.functional.state_query.vertex_attribute_binding.*
TEST=dEQP-GLES31.functional.debug.negative_coverage.log.vertex_array.vertex_attrib_pointer
TEST=dEQP-GLES31.functional.debug.negative_coverage.get_error.vertex_array.vertex_attrib_format
TEST=dEQP-GLES31.functional.debug.negative_coverage.get_error.vertex_array.vertex_attrib_i_format

Change-Id: I4b477a82df6aad89b89b088580a06d66963e6666
Reviewed-on: https://chromium-review.googlesource.com/446124
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/libANGLE/validationES31.cpp b/src/libANGLE/validationES31.cpp
index aec2ade..005d491 100644
--- a/src/libANGLE/validationES31.cpp
+++ b/src/libANGLE/validationES31.cpp
@@ -550,6 +550,153 @@
             Error(GL_INVALID_ENUM, "Invalid program interface: 0x%X", programInterface));
         return false;
     }
+
+    return true;
+}
+
+bool ValidateBindVertexBuffer(ValidationContext *context,
+                              GLuint bindingIndex,
+                              GLuint buffer,
+                              GLintptr offset,
+                              GLsizei stride)
+{
+    if (context->getClientVersion() < ES_3_1)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
+        return false;
+    }
+
+    if (!context->isBufferGenerated(buffer))
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Buffer is not generated."));
+        return false;
+    }
+
+    const Caps &caps = context->getCaps();
+    if (bindingIndex >= caps.maxVertexAttribBindings)
+    {
+        context->handleError(Error(
+            GL_INVALID_VALUE, "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
+        return false;
+    }
+
+    if (offset < 0)
+    {
+        context->handleError(Error(GL_INVALID_VALUE, "offset cannot be negative."));
+        return false;
+    }
+
+    if (stride < 0 || stride > caps.maxVertexAttribStride)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "stride must be between 0 and MAX_VERTEX_ATTRIB_STRIDE."));
+        return false;
+    }
+
+    // [OpenGL ES 3.1] Section 10.3.1 page 244:
+    // An INVALID_OPERATION error is generated if the default vertex array object is bound.
+    if (context->getGLState().getVertexArrayId() == 0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Default vertex array buffer is bound."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateVertexBindingDivisor(ValidationContext *context, GLuint bindingIndex, GLuint divisor)
+{
+    if (context->getClientVersion() < ES_3_1)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
+        return false;
+    }
+
+    const Caps &caps = context->getCaps();
+    if (bindingIndex >= caps.maxVertexAttribBindings)
+    {
+        context->handleError(Error(
+            GL_INVALID_VALUE, "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
+        return false;
+    }
+
+    // [OpenGL ES 3.1] Section 10.3.1 page 243:
+    // An INVALID_OPERATION error is generated if the default vertex array object is bound.
+    if (context->getGLState().getVertexArrayId() == 0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Default vertex array object is bound."));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateVertexAttribFormat(ValidationContext *context,
+                                GLuint attribIndex,
+                                GLint size,
+                                GLenum type,
+                                GLuint relativeOffset,
+                                GLboolean pureInteger)
+{
+    if (context->getClientVersion() < ES_3_1)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
+        return false;
+    }
+
+    const Caps &caps = context->getCaps();
+    if (relativeOffset > static_cast<GLuint>(caps.maxVertexAttribRelativeOffset))
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE,
+                  "relativeOffset cannot be greater than MAX_VERTEX_ATTRIB_RELATIVE_OFFSET."));
+        return false;
+    }
+
+    // [OpenGL ES 3.1] Section 10.3.1 page 243:
+    // An INVALID_OPERATION error is generated if the default vertex array object is bound.
+    if (context->getGLState().getVertexArrayId() == 0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Default vertex array object is bound."));
+        return false;
+    }
+
+    return ValidateVertexFormatBase(context, attribIndex, size, type, pureInteger);
+}
+
+bool ValidateVertexAttribBinding(ValidationContext *context,
+                                 GLuint attribIndex,
+                                 GLuint bindingIndex)
+{
+    if (context->getClientVersion() < ES_3_1)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
+        return false;
+    }
+
+    // [OpenGL ES 3.1] Section 10.3.1 page 243:
+    // An INVALID_OPERATION error is generated if the default vertex array object is bound.
+    if (context->getGLState().getVertexArrayId() == 0)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Default vertex array object is bound."));
+        return false;
+    }
+
+    const Caps &caps = context->getCaps();
+    if (attribIndex >= caps.maxVertexAttributes)
+    {
+        context->handleError(
+            Error(GL_INVALID_VALUE, "attribindex must be smaller than MAX_VERTEX_ATTRIBS."));
+        return false;
+    }
+
+    if (bindingIndex >= caps.maxVertexAttribBindings)
+    {
+        context->handleError(Error(GL_INVALID_VALUE,
+                                   "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS"));
+        return false;
+    }
+
     return true;
 }