Take origin when creating/updating backend texture using pixmaps.

Bug: skia:11042

Change-Id: I511c7556f97f19d7f162031c245019d2da33c129
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/341005
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
diff --git a/src/gpu/GrDataUtils.h b/src/gpu/GrDataUtils.h
index 6b17b46..a3df933 100644
--- a/src/gpu/GrDataUtils.h
+++ b/src/gpu/GrDataUtils.h
@@ -10,11 +10,9 @@
 
 #include "include/core/SkColor.h"
 #include "include/private/GrTypesPriv.h"
-#include "src/gpu/GrColorInfo.h"
+#include "src/gpu/GrImageInfo.h"
 #include "src/gpu/GrSwizzle.h"
 
-class GrImageInfo;
-
 size_t GrNumBlocks(SkImage::CompressionType, SkISize baseDimensions);
 
 // Returns a value that can be used to set rowBytes for a transfer function.
@@ -39,6 +37,13 @@
                      const GrImageInfo& srcInfo, const void* src, size_t srcRB,
                      bool flipY = false);
 
+// Convenience version for src/dst pixmaps.
+inline bool GrConvertPixels(const SkPixmap& dst, const SkPixmap& src, bool flipY = false) {
+    return GrConvertPixels(dst.info(), dst.writable_addr(), dst.rowBytes(),
+                           src.info(),          src.addr(), src.rowBytes(),
+                           flipY);
+}
+
 /** Clears the dst image to a constant color. */
 bool GrClearImage(const GrImageInfo& dstInfo, void* dst, size_t dstRB, SkColor4f color);
 
diff --git a/src/gpu/GrDirectContext.cpp b/src/gpu/GrDirectContext.cpp
index 6ababe8..988f567 100644
--- a/src/gpu/GrDirectContext.cpp
+++ b/src/gpu/GrDirectContext.cpp
@@ -484,6 +484,34 @@
     return beTex;
 }
 
+static bool update_texture_with_pixmaps(GrGpu* gpu,
+                                        const SkPixmap* srcData,
+                                        int numLevels,
+                                        const GrBackendTexture& backendTexture,
+                                        GrSurfaceOrigin textureOrigin,
+                                        sk_sp<GrRefCntedCallback> finishedCallback) {
+    std::unique_ptr<char[]> tempStorage;
+    SkAutoSTArray<15, SkPixmap> tempPixmaps;
+    if (textureOrigin == kBottomLeft_GrSurfaceOrigin) {
+        size_t size = 0;
+        for (int i = 0; i < numLevels; ++i) {
+            size += srcData[i].info().minRowBytes()*srcData[i].height();
+        }
+        tempStorage.reset(new char[size]);
+        tempPixmaps.reset(numLevels);
+        size = 0;
+        for (int i = 0; i < numLevels; ++i) {
+            size_t tempRB = srcData[i].info().minRowBytes();
+            tempPixmaps[i].reset(srcData[i].info(), tempStorage.get() + size, tempRB);
+            SkAssertResult(GrConvertPixels(tempPixmaps[i], srcData[i], /*flip*/ true));
+            size += tempRB*srcData[i].height();
+        }
+        srcData = tempPixmaps.get();
+    }
+    GrGpu::BackendTextureData data(srcData);
+    return gpu->updateBackendTexture(backendTexture, std::move(finishedCallback), &data);
+}
+
 GrBackendTexture GrDirectContext::createBackendTexture(int width, int height,
                                                        const GrBackendFormat& backendFormat,
                                                        const SkColor4f& color,
@@ -535,6 +563,7 @@
 
 GrBackendTexture GrDirectContext::createBackendTexture(const SkPixmap srcData[],
                                                        int numProvidedLevels,
+                                                       GrSurfaceOrigin textureOrigin,
                                                        GrRenderable renderable,
                                                        GrProtected isProtected,
                                                        GrGpuFinishedProc finishedProc,
@@ -567,11 +596,25 @@
     }
 
     GrBackendFormat backendFormat = this->defaultBackendFormat(colorType, renderable);
-
-    GrGpu::BackendTextureData data(srcData);
-    return create_and_update_backend_texture(this, {baseWidth, baseHeight},
-                                             backendFormat, mipMapped, renderable, isProtected,
-                                             std::move(finishedCallback), &data);
+    GrBackendTexture beTex = this->createBackendTexture(srcData[0].width(),
+                                                        srcData[0].height(),
+                                                        backendFormat,
+                                                        mipMapped,
+                                                        renderable,
+                                                        isProtected);
+    if (!beTex.isValid()) {
+        return {};
+    }
+    if (!update_texture_with_pixmaps(this->priv().getGpu(),
+                                     srcData,
+                                     numProvidedLevels,
+                                     beTex,
+                                     textureOrigin,
+                                     std::move(finishedCallback))) {
+        this->deleteBackendTexture(beTex);
+        return {};
+    }
+    return beTex;
 }
 
 bool GrDirectContext::updateBackendTexture(const GrBackendTexture& backendTexture,
@@ -615,6 +658,7 @@
 bool GrDirectContext::updateBackendTexture(const GrBackendTexture& backendTexture,
                                            const SkPixmap srcData[],
                                            int numLevels,
+                                           GrSurfaceOrigin textureOrigin,
                                            GrGpuFinishedProc finishedProc,
                                            GrGpuFinishedContext finishedContext) {
     auto finishedCallback = GrRefCntedCallback::Make(finishedProc, finishedContext);
@@ -635,9 +679,12 @@
     if (numLevels != numExpectedLevels) {
         return false;
     }
-
-    GrGpu::BackendTextureData data(srcData);
-    return fGpu->updateBackendTexture(backendTexture, std::move(finishedCallback), &data);
+    return update_texture_with_pixmaps(fGpu.get(),
+                                       srcData,
+                                       numLevels,
+                                       backendTexture,
+                                       textureOrigin,
+                                       std::move(finishedCallback));
 }
 
 //////////////////////////////////////////////////////////////////////////////