Output the number of columns and rows written for robust ReadPixels.

BUG=angleproject:1354

Change-Id: Ib78f74d7b1a449468e2c477955f6795dc5dbc811
Reviewed-on: https://chromium-review.googlesource.com/463786
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index ab47a90..64ad879 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -233,12 +233,22 @@
                             GLenum type,
                             GLsizei bufSize,
                             GLsizei *length,
+                            GLsizei *columns,
+                            GLsizei *rows,
                             GLvoid *pixels)
 {
     if (length != nullptr)
     {
         *length = 0;
     }
+    if (rows != nullptr)
+    {
+        *rows = 0;
+    }
+    if (columns != nullptr)
+    {
+        *columns = 0;
+    }
 
     if (width < 0 || height < 0)
     {
@@ -320,8 +330,7 @@
     size_t endByte = endByteOrErr.getResult();
     if (bufSize >= 0)
     {
-
-        if (static_cast<size_t>(bufSize) < endByte)
+        if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
         {
             context->handleError(
                 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
@@ -344,7 +353,7 @@
         }
     }
 
-    if (length != nullptr)
+    if (pixelPackBuffer == nullptr && length != nullptr)
     {
         if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
         {
@@ -356,6 +365,39 @@
         *length = static_cast<GLsizei>(endByte);
     }
 
+    auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
+        angle::CheckedNumeric<int> clippedExtent(length);
+        if (start < 0)
+        {
+            // "subtract" the area that is less than 0
+            clippedExtent += start;
+        }
+
+        const int readExtent = start + length;
+        if (readExtent > bufferSize)
+        {
+            // Subtract the region to the right of the read buffer
+            clippedExtent -= (readExtent - bufferSize);
+        }
+
+        if (!clippedExtent.IsValid())
+        {
+            return 0;
+        }
+
+        return std::max(clippedExtent.ValueOrDie(), 0);
+    };
+
+    if (columns != nullptr)
+    {
+        *columns = getClippedExtent(x, width, readBuffer->getSize().width);
+    }
+
+    if (rows != nullptr)
+    {
+        *rows = getClippedExtent(y, height, readBuffer->getSize().height);
+    }
+
     return true;
 }
 
@@ -2326,7 +2368,8 @@
                         GLenum type,
                         GLvoid *pixels)
 {
-    return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
+    return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
+                                  nullptr, pixels);
 }
 
 bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
@@ -2338,6 +2381,8 @@
                                    GLenum type,
                                    GLsizei bufSize,
                                    GLsizei *length,
+                                   GLsizei *columns,
+                                   GLsizei *rows,
                                    GLvoid *pixels)
 {
     if (!ValidateRobustEntryPoint(context, bufSize))
@@ -2346,7 +2391,7 @@
     }
 
     if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
-                                pixels))
+                                columns, rows, pixels))
     {
         return false;
     }
@@ -2376,7 +2421,7 @@
     }
 
     return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
-                                  pixels);
+                                  nullptr, nullptr, pixels);
 }
 
 bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
@@ -2388,6 +2433,8 @@
                                     GLenum type,
                                     GLsizei bufSize,
                                     GLsizei *length,
+                                    GLsizei *columns,
+                                    GLsizei *rows,
                                     GLvoid *data)
 {
     if (!ValidateRobustEntryPoint(context, bufSize))
@@ -2395,7 +2442,8 @@
         return false;
     }
 
-    if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
+    if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
+                                columns, rows, data))
     {
         return false;
     }