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/validationES3.cpp b/src/libANGLE/validationES3.cpp
index c84f7c4..f5a0aa8 100644
--- a/src/libANGLE/validationES3.cpp
+++ b/src/libANGLE/validationES3.cpp
@@ -1986,6 +1986,7 @@
                 return false;
             }
             break;
+
         case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
         case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
             if (index >= 3u)
@@ -1994,6 +1995,7 @@
                 return false;
             }
             break;
+
         case GL_ATOMIC_COUNTER_BUFFER_START:
         case GL_ATOMIC_COUNTER_BUFFER_SIZE:
         case GL_ATOMIC_COUNTER_BUFFER_BINDING:
@@ -2012,6 +2014,27 @@
                 return false;
             }
             break;
+
+        case GL_VERTEX_BINDING_BUFFER:
+        case GL_VERTEX_BINDING_DIVISOR:
+        case GL_VERTEX_BINDING_OFFSET:
+        case GL_VERTEX_BINDING_STRIDE:
+            if (context->getClientVersion() < ES_3_1)
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM,
+                          "Vertex Attrib Bindings are not supported in this version of GL"));
+                return false;
+            }
+            if (index >= caps.maxVertexAttribBindings)
+            {
+                context->handleError(
+                    Error(GL_INVALID_VALUE,
+                          "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
+                return false;
+            }
+            break;
+
         default:
             context->handleError(Error(GL_INVALID_ENUM));
             return false;
@@ -2291,45 +2314,43 @@
 {
     if (context->getClientMajorVersion() < 3)
     {
-        context->handleError(Error(GL_INVALID_OPERATION,
-                                   "glVertexAttribIPointer requires OpenGL ES 3.0 or higher."));
-        return false;
-    }
-
-    if (index >= MAX_VERTEX_ATTRIBS)
-    {
         context->handleError(
-            Error(GL_INVALID_VALUE, "Index must be less than MAX_VERTEX_ATTRIBS."));
+            Error(GL_INVALID_OPERATION, "VertexAttribIPointer requires OpenGL ES 3.0 or higher."));
         return false;
     }
 
-    if (size < 1 || size > 4)
+    if (!ValidateVertexFormatBase(context, index, size, type, true))
     {
-        context->handleError(Error(GL_INVALID_VALUE, "Size must be between 1 and 4."));
         return false;
     }
 
-    switch (type)
-    {
-        case GL_BYTE:
-        case GL_UNSIGNED_BYTE:
-        case GL_SHORT:
-        case GL_UNSIGNED_SHORT:
-        case GL_INT:
-        case GL_UNSIGNED_INT:
-            break;
-
-        default:
-            context->handleError(Error(GL_INVALID_ENUM, "Unknown vertex attribute type."));
-            return false;
-    }
-
     if (stride < 0)
     {
-        context->handleError(Error(GL_INVALID_VALUE, "Stride cannot be negative."));
+        context->handleError(Error(GL_INVALID_VALUE, "stride cannot be negative."));
         return false;
     }
 
+    const Caps &caps = context->getCaps();
+    if (context->getClientVersion() >= ES_3_1)
+    {
+        if (stride > caps.maxVertexAttribStride)
+        {
+            context->handleError(
+                Error(GL_INVALID_VALUE, "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE."));
+            return false;
+        }
+
+        // [OpenGL ES 3.1] Section 10.3.1 page 245:
+        // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
+        // validation should be inherited.
+        if (index >= caps.maxVertexAttribBindings)
+        {
+            context->handleError(
+                Error(GL_INVALID_VALUE, "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
+            return false;
+        }
+    }
+
     // [OpenGL ES 3.0.2] Section 2.8 page 24:
     // An INVALID_OPERATION error is generated when a non-zero vertex array object
     // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,