Cache common DrawElements states.

Similar to how we cache the base common draw states. This will improve
DrawElements performance. Several state checks are optimized into a
single 'if' check of a cached value.

Also includes a regression test for mapping the element array buffer.

Bug: angleproject:2966
Change-Id: Ia6e524a58ad6b7df2e455d67733e15d324b1b893
Reviewed-on: https://chromium-review.googlesource.com/c/1357150
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index 95653e5..9170c07 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -2926,7 +2926,21 @@
         return false;
     }
 
-    // TODO(jmadill): Cache all of these into fast checks. http://anglebug.com/2966
+    intptr_t drawElementsError = context->getStateCache().getBasicDrawElementsError(context);
+    if (drawElementsError)
+    {
+        // All errors from ValidateDrawElementsStates return INVALID_OPERATION.
+        const char *errorMessage = reinterpret_cast<const char *>(drawElementsError);
+        context->validationError(GL_INVALID_OPERATION, errorMessage);
+        return false;
+    }
+
+    // Note that we are missing overflow checks for active transform feedback buffers.
+    return true;
+}
+
+const char *ValidateDrawElementsStates(Context *context)
+{
     const State &state = context->getGLState();
 
     TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
@@ -2940,12 +2954,8 @@
             // It is an invalid operation to call DrawElements, DrawRangeElements or
             // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
             // 86)
-            context->validationError(GL_INVALID_OPERATION,
-                                     kUnsupportedDrawModeForTransformFeedback);
-            return false;
+            return kUnsupportedDrawModeForTransformFeedback;
         }
-
-        // Note that we are missing overflow checks for the transform feedback buffers.
     }
 
     const VertexArray *vao     = state.getVertexArray();
@@ -2957,9 +2967,7 @@
         {
             if (elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
             {
-                context->validationError(GL_INVALID_OPERATION,
-                                         kElementArrayBufferBoundForTransformFeedback);
-                return false;
+                return kElementArrayBufferBoundForTransformFeedback;
             }
         }
         else if (elementArrayBuffer->isMapped())
@@ -2967,8 +2975,7 @@
             // WebGL buffers cannot be mapped/unmapped because the MapBufferRange,
             // FlushMappedBufferRange, and UnmapBuffer entry points are removed from the
             // WebGL 2.0 API. https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
-            context->validationError(GL_INVALID_OPERATION, kBufferMapped);
-            return false;
+            return kBufferMapped;
         }
     }
     else
@@ -2979,12 +2986,11 @@
         if (!context->getGLState().areClientArraysEnabled() ||
             context->getExtensions().webglCompatibility)
         {
-            context->validationError(GL_INVALID_OPERATION, kMustHaveElementArrayBinding);
-            return false;
+            return kMustHaveElementArrayBinding;
         }
     }
 
-    return true;
+    return nullptr;
 }
 
 bool ValidateDrawElementsCommon(Context *context,