Implement a separate last row texture unpack buffer upload workaround

When uploading textures from an unpack buffer, some drivers expect an
extra row paading, causing them to think the pixel buffer is not big enough.
We work around this by uploading the last row separately.

BUG=angleproject:1512

Change-Id: I52fb8b35dc450b957f1fafb0b405c81bf0504157
Reviewed-on: https://chromium-review.googlesource.com/385193
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/libANGLE/validationES3.cpp b/src/libANGLE/validationES3.cpp
index 6f3d800..c6f645c 100644
--- a/src/libANGLE/validationES3.cpp
+++ b/src/libANGLE/validationES3.cpp
@@ -486,44 +486,19 @@
         const gl::Extents size(width, height, depth);
         const auto &unpack = context->getGLState().getUnpackState();
 
-        auto copyBytesOrErr = formatInfo.computeUnpackSize(type, size, unpack);
-        if (copyBytesOrErr.isError())
-        {
-            context->handleError(copyBytesOrErr.getError());
-            return false;
-        }
-        CheckedNumeric<size_t> checkedCopyBytes(copyBytesOrErr.getResult());
-        CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
-        checkedCopyBytes += checkedOffset;
-
-        auto rowPitchOrErr =
-            formatInfo.computeRowPitch(type, width, unpack.alignment, unpack.rowLength);
-        if (rowPitchOrErr.isError())
-        {
-            context->handleError(rowPitchOrErr.getError());
-            return false;
-        }
-        auto depthPitchOrErr = formatInfo.computeDepthPitch(type, width, height, unpack.alignment,
-                                                            unpack.rowLength, unpack.imageHeight);
-        if (depthPitchOrErr.isError())
-        {
-            context->handleError(depthPitchOrErr.getError());
-            return false;
-        }
-
         bool targetIs3D     = target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY;
-        auto skipBytesOrErr = formatInfo.computeSkipBytes(
-            rowPitchOrErr.getResult(), depthPitchOrErr.getResult(), unpack.skipImages,
-            unpack.skipRows, unpack.skipPixels, targetIs3D);
-        if (skipBytesOrErr.isError())
+        auto endByteOrErr   = formatInfo.computeUnpackEndByte(type, size, unpack, targetIs3D);
+        if (endByteOrErr.isError())
         {
-            context->handleError(skipBytesOrErr.getError());
+            context->handleError(endByteOrErr.getError());
             return false;
         }
-        checkedCopyBytes += skipBytesOrErr.getResult();
+        CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
+        CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
+        checkedEndByte += checkedOffset;
 
-        if (!checkedCopyBytes.IsValid() ||
-            (checkedCopyBytes.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
+        if (!checkedEndByte.IsValid() ||
+            (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
         {
             // Overflow past the end of the buffer
             context->handleError(Error(GL_INVALID_OPERATION));