Fix SkQP tests (android 10 cts r3)

bug: 139956393

This addresses a bug where in Q CTS r3 (more recent than that we've used
to validate before), SkQP test cases fail due to glTexSubImage2D not
accounting for different settings for offset and row length.

Test: ./cts-tradefed run cts -m CtsSkQPTestCases on android 10 r3: 0 failures

Change-Id: I771d81bc831b4ea86bc4a985f311c687cb60694a
diff --git a/host/include/libOpenglRender/IOStream.h b/host/include/libOpenglRender/IOStream.h
index 2f699bc..159da1d 100644
--- a/host/include/libOpenglRender/IOStream.h
+++ b/host/include/libOpenglRender/IOStream.h
@@ -94,6 +94,7 @@
     }
 
     void readbackPixels(void* context, int width, int height, unsigned int format, unsigned int type, void* pixels);
+    void uploadPixels(void* context, int width, int height, unsigned int format, unsigned int type, const void* pixels);
 
 
 private:
diff --git a/shared/OpenglCodecCommon/GLClientState.cpp b/shared/OpenglCodecCommon/GLClientState.cpp
index c6140db..3f207b8 100644
--- a/shared/OpenglCodecCommon/GLClientState.cpp
+++ b/shared/OpenglCodecCommon/GLClientState.cpp
@@ -875,6 +875,29 @@
     *skipRows = m_pixelStore.pack_skip_rows;
 }
 
+void GLClientState::getUnpackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const
+{
+    if (width <= 0 || height <= 0) {
+        *startOffset = 0;
+        *pixelRowSize = 0;
+        *totalRowSize = 0;
+        return;
+    }
+
+    GLESTextureUtils::computePackingOffsets2D(
+            width, height,
+            format, type,
+            m_pixelStore.unpack_alignment,
+            m_pixelStore.unpack_row_length,
+            m_pixelStore.unpack_skip_pixels,
+            m_pixelStore.unpack_skip_rows,
+            startOffset,
+            pixelRowSize,
+            totalRowSize);
+
+    *skipRows = m_pixelStore.unpack_skip_rows;
+}
+
 void GLClientState::setNumActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex, GLint numActiveUniforms) {
     UniformBlockInfoKey key;
     key.program = program;
diff --git a/shared/OpenglCodecCommon/GLClientState.h b/shared/OpenglCodecCommon/GLClientState.h
index 5180338..f9f8ee3 100644
--- a/shared/OpenglCodecCommon/GLClientState.h
+++ b/shared/OpenglCodecCommon/GLClientState.h
@@ -254,6 +254,7 @@
     size_t pboNeededDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack) const;
     size_t clearBufferNumElts(GLenum buffer) const;
     void getPackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const;
+    void getUnpackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const;
 
     void setCurrentProgram(GLint program) { m_currentProgram = program; }
     void setCurrentShaderProgram(GLint program) { m_currentShaderProgram = program; }
diff --git a/system/GLESv2_enc/gl2_enc.cpp b/system/GLESv2_enc/gl2_enc.cpp
index 0df93f8..fb70443 100644
--- a/system/GLESv2_enc/gl2_enc.cpp
+++ b/system/GLESv2_enc/gl2_enc.cpp
@@ -3344,7 +3344,7 @@
 	stream->writeFully(&__size_pixels,4);
 	if (useChecksum) checksumCalculator->addBuffer(&__size_pixels,4);
 	if (pixels != NULL) {
-		stream->writeFully(pixels, __size_pixels);
+	    stream->uploadPixels(self, width, height, format, type, pixels);
 		if (useChecksum) checksumCalculator->addBuffer(pixels, __size_pixels);
 	}
 	buf = stream->alloc(checksumSize);
@@ -3497,7 +3497,7 @@
 	stream->writeFully(&__size_pixels,4);
 	if (useChecksum) checksumCalculator->addBuffer(&__size_pixels,4);
 	if (pixels != NULL) {
-		stream->writeFully(pixels, __size_pixels);
+	    stream->uploadPixels(self, width, height, format, type, pixels);
 		if (useChecksum) checksumCalculator->addBuffer(pixels, __size_pixels);
 	}
 	buf = stream->alloc(checksumSize);
diff --git a/system/enc_common/IOStream_common.cpp b/system/enc_common/IOStream_common.cpp
index 901ad1d..1362d3e 100644
--- a/system/enc_common/IOStream_common.cpp
+++ b/system/enc_common/IOStream_common.cpp
@@ -59,3 +59,55 @@
         }
     }
 }
+
+void IOStream::uploadPixels(void* context, int width, int height, unsigned int format, unsigned int type, const void* pixels) {
+    GL2Encoder *ctx = (GL2Encoder *)context;
+    assert (ctx->state() != NULL);
+
+    int startOffset = 0;
+    int pixelRowSize = 0;
+    int totalRowSize = 0;
+    int skipRows = 0;
+
+    ctx->state()->getUnpackingOffsets2D(width, height, format, type,
+                                        &startOffset,
+                                        &pixelRowSize,
+                                        &totalRowSize,
+                                        &skipRows);
+
+    size_t pixelDataSize =
+        ctx->state()->pixelDataSize(
+            width, height, 1, format, type, 0 /* is unpack */);
+
+    if (startOffset == 0 &&
+        pixelRowSize == totalRowSize) {
+        // fast path
+        writeFully(pixels, pixelDataSize);
+    } else if (pixelRowSize == totalRowSize) {
+        // fast path but with skip in the beginning
+        std::vector<char> paddingToDiscard(startOffset, 0);
+        writeFully(&paddingToDiscard[0], startOffset);
+        writeFully((char*)pixels + startOffset, pixelDataSize - startOffset);
+    } else {
+        int totalReadback = 0;
+
+        if (startOffset > 0) {
+            std::vector<char> paddingToDiscard(startOffset, 0);
+            writeFully(&paddingToDiscard[0], startOffset);
+            totalReadback += startOffset;
+        }
+        // need to upload row by row
+        size_t paddingSize = totalRowSize - pixelRowSize;
+        std::vector<char> paddingToDiscard(paddingSize, 0);
+
+        char* start = (char*)pixels + startOffset;
+
+        for (int i = 0; i < height; i++) {
+            writeFully(start, pixelRowSize);
+            totalReadback += pixelRowSize;
+            writeFully(&paddingToDiscard[0], paddingSize);
+            totalReadback += paddingSize;
+            start += totalRowSize;
+        }
+    }
+}