Fix buffer alignment math in draw validation.

We had a bug where we would require "stride * primCount" bytes when
drawing from a buffer, when the last element would not require the
full stride. The correct expression: "stride * (primCount-1) + size.

BUG=angleproject:1086
TEST=dEQP-GLES3.functional.vertex_arrays.single_attribute.strides.*

Change-Id: I7e2897c9d18b0e9849289d033f0ae2573237e4e5
Reviewed-on: https://chromium-review.googlesource.com/287320
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index 2896519..7f28528 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -25,6 +25,73 @@
 
 namespace gl
 {
+namespace
+{
+bool ValidateDrawAttribs(gl::Context *context, GLint primcount, GLint maxVertex)
+{
+    const gl::State &state     = context->getState();
+    const gl::Program *program = state.getProgram();
+
+    const VertexArray *vao     = state.getVertexArray();
+    const auto &vertexAttribs  = vao->getVertexAttributes();
+    const int *semanticIndexes = program->getSemanticIndexes();
+    size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
+    for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
+    {
+        const VertexAttribute &attrib = vertexAttribs[attributeIndex];
+        bool attribActive = (semanticIndexes[attributeIndex] != -1);
+        if (attribActive && attrib.enabled)
+        {
+            gl::Buffer *buffer = attrib.buffer.get();
+
+            if (buffer)
+            {
+                GLint64 attribStride     = static_cast<GLint64>(ComputeVertexAttributeStride(attrib));
+                GLint64 maxVertexElement = 0;
+
+                if (attrib.divisor > 0)
+                {
+                    maxVertexElement =
+                        static_cast<GLint64>(primcount) / static_cast<GLint64>(attrib.divisor);
+                }
+                else
+                {
+                    maxVertexElement = static_cast<GLint64>(maxVertex);
+                }
+
+                // If we're drawing zero vertices, we have enough data.
+                if (maxVertexElement > 0)
+                {
+                    // Note: Last vertex element does not take the full stride!
+                    GLint64 attribSize =
+                        static_cast<GLint64>(ComputeVertexAttributeTypeSize(attrib));
+                    GLint64 attribDataSize = (maxVertexElement - 1) * attribStride + attribSize;
+
+                    // [OpenGL ES 3.0.2] section 2.9.4 page 40:
+                    // We can return INVALID_OPERATION if our vertex attribute does not have
+                    // enough backing data.
+                    if (attribDataSize > buffer->getSize())
+                    {
+                        context->recordError(Error(GL_INVALID_OPERATION));
+                        return false;
+                    }
+                }
+            }
+            else if (attrib.pointer == NULL)
+            {
+                // This is an application error that would normally result in a crash,
+                // but we catch it and return an error
+                context->recordError(Error(
+                    GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer."));
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+}  // anonymous namespace
 
 bool ValidCap(const Context *context, GLenum cap)
 {
@@ -1403,51 +1470,9 @@
     }
 
     // Buffer validations
-    const VertexArray *vao = state.getVertexArray();
-    const auto &vertexAttribs = vao->getVertexAttributes();
-    const int *semanticIndexes = program->getSemanticIndexes();
-    size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
-    for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
+    if (!ValidateDrawAttribs(context, primcount, maxVertex))
     {
-        const VertexAttribute &attrib = vertexAttribs[attributeIndex];
-        bool attribActive = (semanticIndexes[attributeIndex] != -1);
-        if (attribActive && attrib.enabled)
-        {
-            gl::Buffer *buffer = attrib.buffer.get();
-
-            if (buffer)
-            {
-                GLint64 attribStride = static_cast<GLint64>(ComputeVertexAttributeStride(attrib));
-                GLint64 maxVertexElement = 0;
-
-                if (attrib.divisor > 0)
-                {
-                    maxVertexElement = static_cast<GLint64>(primcount) / static_cast<GLint64>(attrib.divisor);
-                }
-                else
-                {
-                    maxVertexElement = static_cast<GLint64>(maxVertex);
-                }
-
-                GLint64 attribDataSize = maxVertexElement * attribStride;
-
-                // [OpenGL ES 3.0.2] section 2.9.4 page 40:
-                // We can return INVALID_OPERATION if our vertex attribute does not have
-                // enough backing data.
-                if (attribDataSize > buffer->getSize())
-                {
-                    context->recordError(Error(GL_INVALID_OPERATION));
-                    return false;
-                }
-            }
-            else if (attrib.pointer == NULL)
-            {
-                // This is an application error that would normally result in a crash,
-                // but we catch it and return an error
-                context->recordError(Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer."));
-                return false;
-            }
-        }
+        return false;
     }
 
     // Uniform buffer validation