Refactor ReadPixels validation.

Move ReadPixels error generation out of the implementation and into
the API level.

BUG=angle:571

Change-Id: I0b32294f359fedd13d1af2c95baf37a3e5ac1d5b
Reviewed-on: https://chromium-review.googlesource.com/188014
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Shannon Woods <shannonwoods@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libGLESv2/validationES.cpp b/src/libGLESv2/validationES.cpp
index 5ed852c..98b353e 100644
--- a/src/libGLESv2/validationES.cpp
+++ b/src/libGLESv2/validationES.cpp
@@ -8,6 +8,8 @@
 // validationES.h: Validation functions for generic OpenGL ES entry point parameters
 
 #include "libGLESv2/validationES.h"
+#include "libGLESv2/validationES2.h"
+#include "libGLESv2/validationES3.h"
 #include "libGLESv2/Context.h"
 #include "libGLESv2/Texture.h"
 #include "libGLESv2/Framebuffer.h"
@@ -771,4 +773,55 @@
     }
 }
 
+bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsizei width, GLsizei height,
+                                  GLenum format, GLenum type, GLsizei *bufSize, GLvoid *pixels)
+{
+    gl::Framebuffer *framebuffer = context->getReadFramebuffer();
+
+    if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
+    {
+        return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
+    }
+
+    if (context->getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0)
+    {
+        return gl::error(GL_INVALID_OPERATION, false);
+    }
+
+    GLenum currentInternalFormat, currentFormat, currentType;
+    int clientVersion = context->getClientVersion();
+
+    // Failure in getCurrentReadFormatType indicates that no color attachment is currently bound,
+    // and attempting to read back if that's the case is an error. The error will be registered
+    // by getCurrentReadFormat.
+    // Note: we need to explicitly check for framebuffer completeness here, before we call
+    // getCurrentReadFormatType, because it generates a different (wrong) error for incomplete FBOs
+    if (!context->getCurrentReadFormatType(&currentInternalFormat, &currentFormat, &currentType))
+        return false;
+
+    bool validReadFormat = (clientVersion < 3) ? ValidES2ReadFormatType(format, type) :
+                                                 ValidES3ReadFormatType(currentInternalFormat, format, type);
+
+    if (!(currentFormat == format && currentType == type) && !validReadFormat)
+    {
+        return gl::error(GL_INVALID_OPERATION, false);
+    }
+
+    GLenum sizedInternalFormat = IsSizedInternalFormat(format, clientVersion) ? format :
+                                 GetSizedInternalFormat(format, type, clientVersion);
+
+    GLsizei outputPitch = GetRowPitch(sizedInternalFormat, type, clientVersion, width, context->getPackAlignment());
+    // sized query sanity check
+    if (bufSize)
+    {
+        int requiredSize = outputPitch * height;
+        if (requiredSize > *bufSize)
+        {
+            return gl::error(GL_INVALID_OPERATION, false);
+        }
+    }
+
+    return true;
+}
+
 }