FramebufferNULL::readPixels: write pixels for tests

BUG=602737

Change-Id: I8c24985358dcd297cb437c501b7a3944e36d98de
Reviewed-on: https://chromium-review.googlesource.com/644210
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/libANGLE/renderer/null/FramebufferNULL.cpp b/src/libANGLE/renderer/null/FramebufferNULL.cpp
index b64dd2a..fcaacb7 100644
--- a/src/libANGLE/renderer/null/FramebufferNULL.cpp
+++ b/src/libANGLE/renderer/null/FramebufferNULL.cpp
@@ -9,7 +9,9 @@
 
 #include "libANGLE/renderer/null/FramebufferNULL.h"
 
+#include "libANGLE/Context.h"
 #include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/null/BufferNULL.h"
 
 #include "common/debug.h"
 
@@ -111,11 +113,60 @@
 }
 
 gl::Error FramebufferNULL::readPixels(const gl::Context *context,
-                                      const gl::Rectangle &area,
+                                      const gl::Rectangle &origArea,
                                       GLenum format,
                                       GLenum type,
-                                      void *pixels) const
+                                      void *ptrOrOffset) const
 {
+    const gl::PixelPackState &packState = context->getGLState().getPackState();
+
+    // Get the pointer to write to from the argument or the pack buffer
+    GLubyte *pixels = nullptr;
+    if (packState.pixelBuffer.get() != nullptr)
+    {
+        BufferNULL *pixelBuffer = GetImplAs<BufferNULL>(packState.pixelBuffer.get());
+        pixels                  = reinterpret_cast<GLubyte *>(pixelBuffer->getDataPtr());
+        pixels += reinterpret_cast<intptr_t>(ptrOrOffset);
+    }
+    else
+    {
+        pixels = reinterpret_cast<GLubyte *>(ptrOrOffset);
+    }
+
+    // Clip read area to framebuffer.
+    const gl::Extents fbSize = getState().getReadAttachment()->getSize();
+    const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
+    gl::Rectangle area;
+    if (!ClipRectangle(origArea, fbRect, &area))
+    {
+        // nothing to read
+        return gl::NoError();
+    }
+
+    // Compute size of unclipped rows and initial skip
+    const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
+
+    GLuint rowBytes = 0;
+    ANGLE_TRY_RESULT(
+        glFormat.computeRowPitch(type, origArea.width, packState.alignment, packState.rowLength),
+        rowBytes);
+
+    GLuint skipBytes = 0;
+    ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, packState, false), skipBytes);
+    pixels += skipBytes;
+
+    // Skip OOB region up to first in bounds pixel
+    int leftClip = area.x - origArea.x;
+    int topClip  = area.y - origArea.y;
+    pixels += leftClip * glFormat.pixelBytes + topClip * rowBytes;
+
+    // Write the in-bounds readpixels data with non-zero values
+    for (GLint y = area.y; y < area.y + area.height; ++y)
+    {
+        memset(pixels, 42, glFormat.pixelBytes * area.width);
+        pixels += rowBytes;
+    }
+
     return gl::NoError();
 }