Add SkEncodedOrigin to SkYUVASizeInfo, fix JPEG orientation in GPU decode path

Bug: skia:7523
Change-Id: I7d48e5f5930b413fa7f27aa391bf92c5af1342e9
Reviewed-on: https://skia-review.googlesource.com/c/173429
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Leon Scroggins <scroggo@google.com>
diff --git a/src/codec/SkJpegCodec.cpp b/src/codec/SkJpegCodec.cpp
index 77ec70f..ca3ac3b 100644
--- a/src/codec/SkJpegCodec.cpp
+++ b/src/codec/SkJpegCodec.cpp
@@ -854,6 +854,8 @@
     // JPEG never has an alpha channel
     sizeInfo->fSizes[3].fHeight = sizeInfo->fSizes[3].fWidth = sizeInfo->fWidthBytes[3] = 0;
 
+    sizeInfo->fOrigin = this->getOrigin();
+
     if (colorSpace) {
         *colorSpace = kJPEG_SkYUVColorSpace;
     }
diff --git a/src/core/SkPixmap.cpp b/src/core/SkPixmap.cpp
index 8f550f8..316614e 100644
--- a/src/core/SkPixmap.cpp
+++ b/src/core/SkPixmap.cpp
@@ -434,7 +434,7 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////////////
 
-static bool draw_orientation(const SkPixmap& dst, const SkPixmap& src, unsigned flags) {
+static bool draw_orientation(const SkPixmap& dst, const SkPixmap& src, SkEncodedOrigin origin) {
     auto surf = SkSurface::MakeRasterDirect(dst.info(), dst.writable_addr(), dst.rowBytes());
     if (!surf) {
         return false;
@@ -443,26 +443,8 @@
     SkBitmap bm;
     bm.installPixels(src);
 
-    SkMatrix m;
-    m.setIdentity();
+    SkMatrix m = SkEncodedOriginToMatrix(origin, src.width(), src.height());
 
-    SkScalar W = SkIntToScalar(src.width());
-    SkScalar H = SkIntToScalar(src.height());
-    if (flags & SkPixmapPriv::kSwapXY) {
-        SkMatrix s;
-        s.setAll(0, 1, 0, 1, 0, 0, 0, 0, 1);
-        m.postConcat(s);
-        using std::swap;
-        swap(W, H);
-    }
-    if (flags & SkPixmapPriv::kMirrorX) {
-        m.postScale(-1, 1);
-        m.postTranslate(W, 0);
-    }
-    if (flags & SkPixmapPriv::kMirrorY) {
-        m.postScale(1, -1);
-        m.postTranslate(0, H);
-    }
     SkPaint p;
     p.setBlendMode(SkBlendMode::kSrc);
     surf->getCanvas()->concat(m);
@@ -470,8 +452,7 @@
     return true;
 }
 
-bool SkPixmapPriv::Orient(const SkPixmap& dst, const SkPixmap& src, OrientFlags flags) {
-    SkASSERT((flags & ~(kMirrorX | kMirrorY | kSwapXY)) == 0);
+bool SkPixmapPriv::Orient(const SkPixmap& dst, const SkPixmap& src, SkEncodedOrigin origin) {
     if (src.colorType() != dst.colorType()) {
         return false;
     }
@@ -479,7 +460,7 @@
 
     int w = src.width();
     int h = src.height();
-    if (flags & kSwapXY) {
+    if (ShouldSwapWidthHeight(origin)) {
         using std::swap;
         swap(w, h);
     }
@@ -492,34 +473,14 @@
 
     // check for aliasing to self
     if (src.addr() == dst.addr()) {
-        return flags == 0;
+        return kTopLeft_SkEncodedOrigin == origin;
     }
-    return draw_orientation(dst, src, flags);
+    return draw_orientation(dst, src, origin);
 }
 
-#define kMirrorX    SkPixmapPriv::kMirrorX
-#define kMirrorY    SkPixmapPriv::kMirrorY
-#define kSwapXY     SkPixmapPriv::kSwapXY
-
-static constexpr uint8_t gOrientationFlags[] = {
-    0,                              // kTopLeft_SkEncodedOrigin
-    kMirrorX,                       // kTopRight_SkEncodedOrigin
-    kMirrorX | kMirrorY,            // kBottomRight_SkEncodedOrigin
-               kMirrorY,            // kBottomLeft_SkEncodedOrigin
-                          kSwapXY,  // kLeftTop_SkEncodedOrigin
-    kMirrorX            | kSwapXY,  // kRightTop_SkEncodedOrigin
-    kMirrorX | kMirrorY | kSwapXY,  // kRightBottom_SkEncodedOrigin
-               kMirrorY | kSwapXY,  // kLeftBottom_SkEncodedOrigin
-};
-
-SkPixmapPriv::OrientFlags SkPixmapPriv::OriginToOrient(SkEncodedOrigin o) {
-    unsigned io = static_cast<int>(o) - 1;
-    SkASSERT(io < SK_ARRAY_COUNT(gOrientationFlags));
-    return static_cast<SkPixmapPriv::OrientFlags>(gOrientationFlags[io]);
-}
-
-bool SkPixmapPriv::ShouldSwapWidthHeight(SkEncodedOrigin o) {
-    return SkToBool(OriginToOrient(o) & kSwapXY);
+bool SkPixmapPriv::ShouldSwapWidthHeight(SkEncodedOrigin origin) {
+    // The last four SkEncodedOrigin values involve 90 degree rotations
+    return origin >= kLeftTop_SkEncodedOrigin;
 }
 
 SkImageInfo SkPixmapPriv::SwapWidthHeight(const SkImageInfo& info) {
diff --git a/src/core/SkPixmapPriv.h b/src/core/SkPixmapPriv.h
index cced3e2..4f3b3b5 100644
--- a/src/core/SkPixmapPriv.h
+++ b/src/core/SkPixmapPriv.h
@@ -14,20 +14,11 @@
 
 class SkPixmapPriv {
 public:
-    // These flag are applied in this order (swap is applied last)
-    enum OrientFlags {
-        kMirrorX = 1 << 0,
-        kMirrorY = 1 << 1,
-        kSwapXY  = 1 << 2,
-    };
-
-    static OrientFlags OriginToOrient(SkEncodedOrigin);
-
     /**
      *  Copy the pixels in this pixmap into dst, applying the orientation transformations specified
      *  by the flags. If the inputs are invalid, this returns false and no copy is made.
      */
-    static bool Orient(const SkPixmap& dst, const SkPixmap& src, OrientFlags);
+    static bool Orient(const SkPixmap& dst, const SkPixmap& src, SkEncodedOrigin);
 
     static bool ShouldSwapWidthHeight(SkEncodedOrigin o);
     static SkImageInfo SwapWidthHeight(const SkImageInfo& info);
@@ -59,7 +50,7 @@
             return false;
         }
         if (tmp != &dst) {
-            return Orient(dst, *tmp, OriginToOrient(origin));
+            return Orient(dst, *tmp, origin);
         }
         return true;
     }
@@ -71,4 +62,3 @@
 };
 
 #endif
-
diff --git a/src/gpu/GrYUVProvider.cpp b/src/gpu/GrYUVProvider.cpp
index 16027df..6b3eb88 100644
--- a/src/gpu/GrYUVProvider.cpp
+++ b/src/gpu/GrYUVProvider.cpp
@@ -182,7 +182,8 @@
     const SkRect r = SkRect::MakeIWH(yuvSizeInfo.fSizes[0].fWidth,
                                      yuvSizeInfo.fSizes[0].fHeight);
 
-    renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), r);
+    SkMatrix m = SkEncodedOriginToMatrix(yuvSizeInfo.fOrigin, r.width(), r.height());
+    renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, m, r);
 
     return renderTargetContext->asTextureProxyRef();
 }