Revert "Add function to GrDataUtils to handle color conversions."

This reverts commit 55091020435c876d12f2d74697b21edbc98e13fa.

Reason for revert: valgrind issues

Original change's description:
> Add function to GrDataUtils to handle color conversions.
> 
> Like SkConvertPixels but knows about all GrColorTypes, origin, and can
> apply an arbitrary GrSwizzle.
> 
> Use in GrSurfaceContext read/write pixels methods.
> 
> Add support for '0' to GrSwizzle.
> 
> 
> Change-Id: Ib9dd215fcb0ee8b33c4020893c22b4ab7ce1f40b
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/220761
> Commit-Queue: Brian Salomon <bsalomon@google.com>
> Reviewed-by: Greg Daniel <egdaniel@google.com>

TBR=egdaniel@google.com,bsalomon@google.com,brianosman@google.com

Change-Id: If50f3e26875787d9309009e9c701774fbad0afda
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/221538
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrCaps.cpp b/src/gpu/GrCaps.cpp
index 8f6218d..74e3b70 100644
--- a/src/gpu/GrCaps.cpp
+++ b/src/gpu/GrCaps.cpp
@@ -355,9 +355,3 @@
 GrBackendFormat GrCaps::getBackendFormatFromColorType(SkColorType ct) const {
     return this->getBackendFormatFromGrColorType(SkColorTypeToGrColorType(ct), GrSRGBEncoded::kNo);
 }
-
-GrCaps::SupportedRead GrCaps::supportedReadPixelsColorType(GrPixelConfig config,
-                                                           const GrBackendFormat&,
-                                                           GrColorType dstColorType) const {
-    return SupportedRead{GrSwizzle::RGBA(), GrPixelConfigToColorType(config)};
-}
diff --git a/src/gpu/GrCaps.h b/src/gpu/GrCaps.h
index c4c0379..4b0bbf8 100644
--- a/src/gpu/GrCaps.h
+++ b/src/gpu/GrCaps.h
@@ -211,26 +211,18 @@
      * the data into in order to use GrGpu::writePixels().
      */
     virtual GrColorType supportedWritePixelsColorType(GrPixelConfig config,
-                                                      GrColorType srcColorType) const {
+                                                      GrColorType /*srcColorType*/) const {
         return GrPixelConfigToColorType(config);
     }
 
-    struct SupportedRead {
-        GrSwizzle fSwizzle;
-        GrColorType fColorType;
-    };
-
     /**
-     * Given a src surface's pixel config and its backend format as well as a color type the caller
-     * would like read into, this provides a legal color type that the caller may pass to
-     * GrGpu::readPixels(). The returned color type may differ from the passed dstColorType, in
-     * which case the caller must convert the read pixel data (see GrConvertPixels). When converting
-     * to dstColorType the swizzle in the returned struct should be applied. The caller must check
-     * the returned color type for kUnknown.
+     * Given a src pixel config and a dst color type what color type must the caller read to using
+     * GrGpu::readPixels() and then coax into dstColorType.
      */
-    virtual SupportedRead supportedReadPixelsColorType(GrPixelConfig srcConfig,
-                                                       const GrBackendFormat& srcFormat,
-                                                       GrColorType dstColorType) const;
+    virtual GrColorType supportedReadPixelsColorType(GrPixelConfig config,
+                                                     GrColorType /*dstColorType*/) const {
+        return GrPixelConfigToColorType(config);
+    }
 
     /** Are transfer buffers (to textures and from surfaces) supported? */
     bool transferBufferSupport() const { return fTransferBufferSupport; }
diff --git a/src/gpu/GrDataUtils.cpp b/src/gpu/GrDataUtils.cpp
index abfe351..965251e 100644
--- a/src/gpu/GrDataUtils.cpp
+++ b/src/gpu/GrDataUtils.cpp
@@ -6,9 +6,8 @@
  */
 
 #include "src/gpu/GrDataUtils.h"
+
 #include "include/private/GrColor.h"
-#include "src/core/SkColorSpaceXformSteps.h"
-#include "src/core/SkTLazy.h"
 #include "src/core/SkUtils.h"
 
 struct ETC1Block {
@@ -360,190 +359,3 @@
     }
 }
 
-static GrSwizzle get_load_and_get_swizzle(GrColorType ct, SkRasterPipeline::StockStage* load,
-                                          bool* isNormalized) {
-    GrSwizzle swizzle("rgba");
-    *isNormalized = true;
-    switch (ct) {
-        case GrColorType::kAlpha_8:          *load = SkRasterPipeline::load_a8;      break;
-        case GrColorType::kRGB_565:          *load = SkRasterPipeline::load_565;     break;
-        case GrColorType::kABGR_4444:        *load = SkRasterPipeline::load_4444;    break;
-        case GrColorType::kRGBA_8888:        *load = SkRasterPipeline::load_8888;    break;
-        case GrColorType::kRG_88:            *load = SkRasterPipeline::load_rg88;    break;
-        case GrColorType::kRGBA_1010102:     *load = SkRasterPipeline::load_1010102; break;
-        case GrColorType::kAlpha_F16:        *load = SkRasterPipeline::load_af16;    break;
-        case GrColorType::kRGBA_F16_Clamped: *load = SkRasterPipeline::load_f16;     break;
-        case GrColorType::kRG_1616:          *load = SkRasterPipeline::load_rg1616;  break;
-
-        case GrColorType::kRGBA_F16:         *load = SkRasterPipeline::load_f16;
-                                             *isNormalized = false;
-                                             break;
-        case GrColorType::kRG_F32:           *load = SkRasterPipeline::load_rgf32;
-                                             *isNormalized = false;
-                                             break;
-        case GrColorType::kRGBA_F32:         *load = SkRasterPipeline::load_f32;
-                                             *isNormalized = false;
-                                             break;
-        case GrColorType::kR_16:             *load = SkRasterPipeline::load_a16;
-                                             swizzle = GrSwizzle("a001");
-                                             break;
-        case GrColorType::kGray_8:           *load = SkRasterPipeline::load_a8;
-                                             swizzle = GrSwizzle("aaa1");
-                                             break;
-        case GrColorType::kBGRA_8888:        *load = SkRasterPipeline::load_8888;
-                                             swizzle = GrSwizzle("bgra");
-                                             break;
-        case GrColorType::kRGB_888x:         *load = SkRasterPipeline::load_8888;
-                                             swizzle = GrSwizzle("rgb1");
-                                             break;
-
-        case GrColorType::kUnknown:
-        case GrColorType::kRGB_ETC1:
-            SK_ABORT("unexpected CT");
-    }
-    return swizzle;
-}
-
-static GrSwizzle get_dst_swizzle_and_store(GrColorType ct, SkRasterPipeline::StockStage* store,
-                                           bool* isNormalized) {
-    GrSwizzle swizzle("rgba");
-    *isNormalized = true;
-    switch (ct) {
-        case GrColorType::kAlpha_8:          *store = SkRasterPipeline::store_a8;      break;
-        case GrColorType::kRGB_565:          *store = SkRasterPipeline::store_565;     break;
-        case GrColorType::kABGR_4444:        *store = SkRasterPipeline::store_4444;    break;
-        case GrColorType::kRGBA_8888:        *store = SkRasterPipeline::store_8888;    break;
-        case GrColorType::kRG_88:            *store = SkRasterPipeline::store_rg88;    break;
-        case GrColorType::kRGBA_1010102:     *store = SkRasterPipeline::store_1010102; break;
-        case GrColorType::kRGBA_F16_Clamped: *store = SkRasterPipeline::store_f16;     break;
-        case GrColorType::kRG_1616:          *store = SkRasterPipeline::store_rg1616;  break;
-
-        case GrColorType::kAlpha_F16:        *store = SkRasterPipeline::store_af16;
-                                             *isNormalized = false;
-                                             break;
-        case GrColorType::kRGBA_F16:         *store = SkRasterPipeline::store_f16;
-                                             *isNormalized = false;
-                                             break;
-        case GrColorType::kRG_F32:           *store = SkRasterPipeline::store_rgf32;
-                                             *isNormalized = false;
-                                             break;
-        case GrColorType::kRGBA_F32:         *store = SkRasterPipeline::store_f32;
-                                             *isNormalized = false;
-                                             break;
-        case GrColorType::kR_16:             swizzle = GrSwizzle("000r");
-                                             *store = SkRasterPipeline::store_a16;
-                                             break;
-        case GrColorType::kBGRA_8888:        swizzle = GrSwizzle("bgra");
-                                             *store = SkRasterPipeline::store_8888;
-                                             break;
-        case GrColorType::kRGB_888x:         swizzle = GrSwizzle("rgb1");
-                                             *store = SkRasterPipeline::store_8888;
-                                             break;
-
-        case GrColorType::kGray_8:  // not currently supported as output
-        case GrColorType::kUnknown:
-        case GrColorType::kRGB_ETC1:
-            SK_ABORT("unexpected CT");
-    }
-    return swizzle;
-}
-
-static inline void append_clamp_gamut(SkRasterPipeline* pipeline) {
-    // SkRasterPipeline may not know our color type and also doesn't like caller to directly
-    // append clamp_gamut. Fake it out.
-    static SkImageInfo fakeII = SkImageInfo::MakeN32Premul(1, 1);
-    pipeline->append_gamut_clamp_if_normalized(fakeII);
-}
-
-bool GrConvertPixels(const GrPixelInfo& dstInfo, void* dst, const GrPixelInfo& srcInfo,
-                     const void* src, GrSwizzle swizzle) {
-    if (dstInfo.fWidth != srcInfo.fWidth || srcInfo.fHeight != dstInfo.fHeight) {
-        return false;
-    }
-    if (dstInfo.fWidth <= 0 || dstInfo.fHeight <= 0) {
-        return false;
-    }
-    if (GrColorTypeComponentFlags(dstInfo.fColorInfo.fColorType) & kGray_SkColorTypeComponentFlag) {
-        // We don't currently support conversion to Gray.
-        return false;
-    }
-    size_t srcBpp = GrColorTypeBytesPerPixel(srcInfo.fColorInfo.fColorType);
-    size_t dstBpp = GrColorTypeBytesPerPixel(dstInfo.fColorInfo.fColorType);
-    if (!srcBpp || !dstBpp) {
-        // Either src or dst is compressed or kUnknown.
-        return false;
-    }
-    // SkRasterPipeline operates on row-pixels not row-bytes.
-    SkASSERT(dstInfo.fRowBytes % dstBpp == 0);
-    SkASSERT(srcInfo.fRowBytes % srcBpp == 0);
-
-    SkRasterPipeline::StockStage load;
-    bool srcIsNormalized;
-    auto loadSwizzle =
-            get_load_and_get_swizzle(srcInfo.fColorInfo.fColorType, &load, &srcIsNormalized);
-    loadSwizzle = GrSwizzle::Concat(loadSwizzle, swizzle);
-
-    SkRasterPipeline::StockStage store;
-    bool dstIsNormalized;
-    auto storeSwizzle =
-            get_dst_swizzle_and_store(dstInfo.fColorInfo.fColorType, &store, &dstIsNormalized);
-
-    bool alphaOrCSConversion =
-            (srcInfo.fColorInfo.fAlphaType != dstInfo.fColorInfo.fAlphaType &&
-             srcInfo.fColorInfo.fAlphaType != kOpaque_SkAlphaType) ||
-            !SkColorSpace::Equals(srcInfo.fColorInfo.fColorSpace, dstInfo.fColorInfo.fColorSpace);
-
-    bool clampGamut;
-    SkTLazy<SkColorSpaceXformSteps> steps;
-    GrSwizzle loadStoreSwizzle;
-    if (alphaOrCSConversion) {
-        steps.init(srcInfo.fColorInfo.fColorSpace, srcInfo.fColorInfo.fAlphaType,
-                   dstInfo.fColorInfo.fColorSpace, dstInfo.fColorInfo.fAlphaType);
-        clampGamut = dstIsNormalized && dstInfo.fColorInfo.fAlphaType == kPremul_SkAlphaType;
-    } else {
-        clampGamut = dstIsNormalized && !srcIsNormalized &&
-                     dstInfo.fColorInfo.fAlphaType == kPremul_SkAlphaType;
-        if (!clampGamut) {
-            loadStoreSwizzle = GrSwizzle::Concat(loadSwizzle, storeSwizzle);
-        }
-    }
-    int cnt = 1;
-    int height = srcInfo.fHeight;
-    SkRasterPipeline_MemoryCtx srcCtx{const_cast<void*>(src), SkToInt(srcInfo.fRowBytes / srcBpp)},
-                               dstCtx{                  dst , SkToInt(dstInfo.fRowBytes / dstBpp)};
-    if (srcInfo.fOrigin != dstInfo.fOrigin) {
-        // It *almost* works to point the src at the last row and negate the stride and run the
-        // whole rectangle. However, SkRasterPipeline::run()'s control loop uses size_t loop
-        // variables so it winds up relying on unsigned overflow math. It works out in practice
-        // but UBSAN says "no!" as it's technically undefined and in theory a compiler could emit
-        // code that didn't do what is intended. So we go one row at a time. :(
-        srcCtx.pixels = static_cast<char*>(srcCtx.pixels) + srcInfo.fRowBytes * (height - 1);
-        std::swap(cnt, height);
-    }
-    for (int i = 0; i < cnt; ++i) {
-        SkRasterPipeline_<256> pipeline;
-        pipeline.append(load, &srcCtx);
-
-        if (alphaOrCSConversion) {
-            loadSwizzle.apply(&pipeline);
-            steps->apply(&pipeline, srcIsNormalized);
-            if (clampGamut) {
-                append_clamp_gamut(&pipeline);
-            }
-            storeSwizzle.apply(&pipeline);
-        } else {
-            if (clampGamut) {
-                loadSwizzle.apply(&pipeline);
-                append_clamp_gamut(&pipeline);
-                storeSwizzle.apply(&pipeline);
-            } else {
-                loadStoreSwizzle.apply(&pipeline);
-            }
-        }
-        pipeline.append(store, &dstCtx);
-        pipeline.run(0, 0, srcInfo.fWidth, height);
-        srcCtx.pixels = static_cast<char*>(srcCtx.pixels) - srcInfo.fRowBytes;
-        dstCtx.pixels = static_cast<char*>(dstCtx.pixels) + dstInfo.fRowBytes;
-    }
-    return true;
-}
diff --git a/src/gpu/GrDataUtils.h b/src/gpu/GrDataUtils.h
index fcf7a07..b79e84c 100644
--- a/src/gpu/GrDataUtils.h
+++ b/src/gpu/GrDataUtils.h
@@ -10,7 +10,6 @@
 
 #include "include/core/SkColor.h"
 #include "include/private/GrTypesPriv.h"
-#include "src/gpu/GrSwizzle.h"
 
 // TODO: consolidate all the backend-specific flavors of this method to this
 size_t GrETC1CompressedDataSize(int w, int h);
@@ -34,22 +33,4 @@
                   const SkTArray<size_t>& individualMipOffsets,
                   char* dest, const SkColor4f& color);
 
-struct GrColorInfo {
-    GrColorType fColorType = GrColorType::kUnknown;
-    SkColorSpace* fColorSpace = nullptr;
-    SkAlphaType fAlphaType = kPremul_SkAlphaType;
-};
-
-struct GrPixelInfo {
-    GrColorInfo fColorInfo = {};
-    GrSurfaceOrigin fOrigin = kTopLeft_GrSurfaceOrigin;
-    int fWidth = 0;
-    int fHeight = 0;
-    size_t fRowBytes = 0;
-};
-
-// Swizzle param is applied after loading and before converting from srcInfo to dstInfo.
-bool GrConvertPixels(const GrPixelInfo& dstInfo, void* dst, const GrPixelInfo& srcInfo,
-                     const void* src, GrSwizzle swizzle = GrSwizzle{});
-
 #endif
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 6c8c342..597631c 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -5,7 +5,6 @@
  * found in the LICENSE file.
  */
 
-#include "src/gpu/GrRenderTargetContext.h"
 #include "include/core/SkDrawable.h"
 #include "include/gpu/GrBackendSemaphore.h"
 #include "include/gpu/GrRenderTarget.h"
@@ -27,13 +26,13 @@
 #include "src/gpu/GrBlurUtils.h"
 #include "src/gpu/GrCaps.h"
 #include "src/gpu/GrContextPriv.h"
-#include "src/gpu/GrDataUtils.h"
 #include "src/gpu/GrDrawingManager.h"
 #include "src/gpu/GrFixedClip.h"
 #include "src/gpu/GrGpuResourcePriv.h"
 #include "src/gpu/GrMemoryPool.h"
 #include "src/gpu/GrPathRenderer.h"
 #include "src/gpu/GrRecordingContextPriv.h"
+#include "src/gpu/GrRenderTargetContext.h"
 #include "src/gpu/GrRenderTargetContextPriv.h"
 #include "src/gpu/GrResourceProvider.h"
 #include "src/gpu/GrStencilAttachment.h"
@@ -1961,21 +1960,19 @@
     auto dstCT = SkColorTypeToGrColorType(info.colorType());
     bool needsRescale = srcRect.width() != info.width() || srcRect.height() != info.height();
     GrPixelConfig configOfFinalContext = fRenderTargetProxy->config();
-    auto backendFormatOfFinalContext = fRenderTargetProxy->backendFormat();
     if (needsRescale) {
-        backendFormatOfFinalContext = this->caps()->getBackendFormatFromColorType(info.colorType());
-        configOfFinalContext = this->caps()->getConfigFromBackendFormat(backendFormatOfFinalContext,
-                                                                        info.colorType());
+        auto backendFormat = this->caps()->getBackendFormatFromColorType(info.colorType());
+        configOfFinalContext =
+                this->caps()->getConfigFromBackendFormat(backendFormat, info.colorType());
     }
-    auto readInfo = this->caps()->supportedReadPixelsColorType(configOfFinalContext,
-                                                               backendFormatOfFinalContext, dstCT);
-    // Fail if we can't read from the source surface's color type.
-    if (readInfo.fColorType == GrColorType::kUnknown) {
+    auto readCT = this->caps()->supportedReadPixelsColorType(configOfFinalContext, dstCT);
+    // Fail if we can't do a CPU conversion from readCT to dstCT.
+    if (GrColorTypeToSkColorType(readCT) == kUnknown_SkColorType) {
         callback(context, nullptr, 0);
         return;
     }
     // Fail if readCT does not have all of readCT's color channels.
-    if (GrColorTypeComponentFlags(dstCT) & ~GrColorTypeComponentFlags(readInfo.fColorType)) {
+    if (GrColorTypeComponentFlags(dstCT) & ~GrColorTypeComponentFlags(readCT)) {
         callback(context, nullptr, 0);
         return;
     }
@@ -2045,55 +2042,42 @@
     if (fRenderTargetProxy->wrapsVkSecondaryCB()) {
         return {};
     }
-    auto supportedRead = this->caps()->supportedReadPixelsColorType(
-            fRenderTargetProxy->config(), fRenderTargetProxy->backendFormat(), dstCT);
+    auto readCT = this->caps()->supportedReadPixelsColorType(fRenderTargetProxy->config(), dstCT);
+    // Fail if we can't do a CPU conversion from readCT to dstCT.
+    if (readCT != dstCT && (GrColorTypeToSkColorType(readCT) == kUnknown_SkColorType ||
+                            GrColorTypeToSkColorType(dstCT) == kUnknown_SkColorType)) {
+        return {};
+    }
     // Fail if readCT does not have all of readCT's color channels.
-    if (GrColorTypeComponentFlags(dstCT) & ~GrColorTypeComponentFlags(supportedRead.fColorType)) {
+    if (GrColorTypeComponentFlags(dstCT) & ~GrColorTypeComponentFlags(readCT)) {
         return {};
     }
 
     if (!this->caps()->transferBufferSupport() ||
-        !this->caps()->transferFromOffsetAlignment(supportedRead.fColorType)) {
+        !this->caps()->transferFromOffsetAlignment(readCT)) {
         return {};
     }
 
-    size_t rowBytes = GrColorTypeBytesPerPixel(supportedRead.fColorType) * rect.width();
+    size_t rowBytes = GrColorTypeBytesPerPixel(readCT) * rect.width();
     size_t size = rowBytes * rect.height();
     auto buffer = direct->priv().resourceProvider()->createBuffer(
             size, GrGpuBufferType::kXferGpuToCpu, GrAccessPattern::kStream_GrAccessPattern);
     if (!buffer) {
         return {};
     }
-    auto srcRect = rect;
-    bool flip = this->origin() == kBottomLeft_GrSurfaceOrigin;
-    if (flip) {
-        srcRect = SkIRect::MakeLTRB(rect.fLeft, this->height() - rect.fBottom, rect.fRight,
-                                    this->height() - rect.fTop);
-    }
-    auto op = GrTransferFromOp::Make(fContext, srcRect, supportedRead.fColorType, buffer, 0);
-    this->getRTOpList()->addOp(std::move(op), *this->caps());
+    this->getRTOpList()->addOp(GrTransferFromOp::Make(fContext, rect, readCT, buffer, 0),
+                               *this->caps());
     PixelTransferResult result;
     result.fTransferBuffer = std::move(buffer);
-    if (supportedRead.fColorType != dstCT || supportedRead.fSwizzle != GrSwizzle("rgba") || flip) {
-        result.fPixelConverter = [w = rect.width(), h = rect.height(), dstCT, supportedRead](
-                                         void* dst, const void* src) {
-            GrPixelInfo srcInfo;
-            srcInfo.fColorInfo.fAlphaType = kPremul_SkAlphaType;
-            srcInfo.fColorInfo.fColorType = supportedRead.fColorType;
-            srcInfo.fColorInfo.fColorSpace = nullptr;
-            srcInfo.fRowBytes = GrColorTypeBytesPerPixel(supportedRead.fColorType) * w;
-
-            GrPixelInfo dstInfo;
-            dstInfo.fColorInfo.fAlphaType = kPremul_SkAlphaType;
-            dstInfo.fColorInfo.fColorType = dstCT;
-            dstInfo.fColorInfo.fColorSpace = nullptr;
-            dstInfo.fRowBytes = GrColorTypeBytesPerPixel(dstCT) * w;
-
-            srcInfo.fWidth  = dstInfo.fWidth  = w;
-            srcInfo.fHeight = dstInfo.fHeight = h;
-
-            GrConvertPixels(dstInfo, dst, srcInfo, src, supportedRead.fSwizzle);
-        };
+    if (readCT != dstCT) {
+        result.fPixelConverter =
+                [w = rect.width(), h = rect.height(), dstCT = GrColorTypeToSkColorType(dstCT),
+                 srcCT = GrColorTypeToSkColorType(readCT)](void* dst, const void* src) {
+                    auto dstII = SkImageInfo::Make(w, h, dstCT, kPremul_SkAlphaType, nullptr);
+                    auto srcII = SkImageInfo::Make(w, h, srcCT, kPremul_SkAlphaType, nullptr);
+                    SkConvertPixels(dstII, dst, w * SkColorTypeBytesPerPixel(dstCT), srcII, src,
+                                    w * SkColorTypeBytesPerPixel(srcCT));
+                };
     }
     return result;
 }
@@ -2225,16 +2209,26 @@
         callback(context, nullptr, nullptr);
         return;
     }
-    const auto backendFormat = this->caps()->getBackendFormatFromGrColorType(GrColorType::kAlpha_8,
-                                                                             GrSRGBEncoded::kNo);
+    GrPixelConfig planeConfig = kAlpha_8_GrPixelConfig;
+    GrColorType planeColorType = GrColorType::kAlpha_8;
+    if (this->caps()->supportedReadPixelsColorType(planeConfig, planeColorType) !=
+        GrColorType::kAlpha_8) {
+        // TODO: Because there are issues with reading back/transferring A8 textures on GL, we are
+        // currently using RGBA textures for the planes. Fix this once the A8 read back/transfer
+        // issues are addressed.
+        planeConfig = kRGBA_8888_GrPixelConfig;
+        planeColorType = GrColorType::kRGBA_8888;
+    }
+    const auto backendFormat = this->caps()->getBackendFormatFromGrColorType(
+            planeColorType, GrSRGBEncoded::kNo);
     auto yRTC = direct->priv().makeDeferredRenderTargetContext(
-            backendFormat, SkBackingFit::kApprox, dstW, dstH, kAlpha_8_GrPixelConfig, dstColorSpace,
+            backendFormat, SkBackingFit::kApprox, dstW, dstH, planeConfig, dstColorSpace,
             1, GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin);
     auto uRTC = direct->priv().makeDeferredRenderTargetContext(
-            backendFormat, SkBackingFit::kApprox, dstW / 2, dstH / 2, kAlpha_8_GrPixelConfig,
+            backendFormat, SkBackingFit::kApprox, dstW / 2, dstH / 2, planeConfig,
             dstColorSpace, 1, GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin);
     auto vRTC = direct->priv().makeDeferredRenderTargetContext(
-            backendFormat, SkBackingFit::kApprox, dstW / 2, dstH / 2, kAlpha_8_GrPixelConfig,
+            backendFormat, SkBackingFit::kApprox, dstW / 2, dstH / 2, planeConfig,
             dstColorSpace, 1, GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin);
     if (!yRTC || !uRTC || !vRTC) {
         callback(context, nullptr, nullptr);
diff --git a/src/gpu/GrSurfaceContext.cpp b/src/gpu/GrSurfaceContext.cpp
index 4b29ce0..71113b4 100644
--- a/src/gpu/GrSurfaceContext.cpp
+++ b/src/gpu/GrSurfaceContext.cpp
@@ -13,7 +13,6 @@
 #include "src/core/SkAutoPixmapStorage.h"
 #include "src/gpu/GrClip.h"
 #include "src/gpu/GrContextPriv.h"
-#include "src/gpu/GrDataUtils.h"
 #include "src/gpu/GrDrawingManager.h"
 #include "src/gpu/GrGpu.h"
 #include "src/gpu/GrRecordingContextPriv.h"
@@ -225,52 +224,71 @@
                                        buffer, rowBytes, flags);
     }
 
+    bool convert = unpremul || needColorConversion;
+
     bool flip = srcProxy->origin() == kBottomLeft_GrSurfaceOrigin;
-    auto supportedRead = caps->supportedReadPixelsColorType(
-            srcProxy->config(), srcProxy->backendFormat(), dstColorType);
+    if (flip) {
+        top = srcSurface->height() - top - height;
+    }
 
-    bool convert = unpremul || needColorConversion || flip ||
-                   (dstColorType != supportedRead.fColorType) ||
-                   supportedRead.fSwizzle != GrSwizzle::RGBA();
+    GrColorType allowedColorType = caps->supportedReadPixelsColorType(srcProxy->config(),
+                                                                      dstColorType);
+    convert = convert || (dstColorType != allowedColorType);
 
-    std::unique_ptr<char[]> tmpPixels;
-    GrPixelInfo tmpInfo;
-    GrPixelInfo dstInfo;
-    void* readDst = buffer;
+    SkAutoPixmapStorage tempPixmap;
+    SkPixmap finalPixmap;
     if (convert) {
-        tmpInfo.fColorInfo.fColorType = supportedRead.fColorType;
-        tmpInfo.fColorInfo.fAlphaType = kPremul_SkAlphaType;
-        tmpInfo.fColorInfo.fColorSpace = this->colorSpaceInfo().colorSpace();
-        tmpInfo.fOrigin = srcProxy->origin();
-        tmpInfo.fRowBytes = GrColorTypeBytesPerPixel(supportedRead.fColorType) * width;
-
-        dstInfo.fColorInfo.fColorType = dstColorType;
-        dstInfo.fColorInfo.fAlphaType = unpremul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType;
-        dstInfo.fColorInfo.fColorSpace = dstColorSpace;
-        dstInfo.fOrigin = kTopLeft_GrSurfaceOrigin;
-        dstInfo.fRowBytes = rowBytes;
-
-        dstInfo.fWidth = tmpInfo.fWidth = width;
-        dstInfo.fHeight = tmpInfo.fHeight = height;
-
-        size_t size = tmpInfo.fRowBytes * height;
-        tmpPixels.reset(new char[size]);
-        // Chrome MSAN bots require this.
-        sk_bzero(tmpPixels.get(), size);
-        readDst = tmpPixels.get();
-        rowBytes = tmpInfo.fRowBytes;
-        top = flip ? srcSurface->height() - top - height : top;
+        SkColorType srcSkColorType = GrColorTypeToSkColorType(allowedColorType);
+        SkColorType dstSkColorType = GrColorTypeToSkColorType(dstColorType);
+        bool srcAlwaysOpaque = SkColorTypeIsAlwaysOpaque(srcSkColorType);
+        bool dstAlwaysOpaque = SkColorTypeIsAlwaysOpaque(dstSkColorType);
+        if (kUnknown_SkColorType == srcSkColorType || kUnknown_SkColorType == dstSkColorType) {
+            return false;
+        }
+        auto tempAT = srcAlwaysOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
+        auto tempII = SkImageInfo::Make(width, height, srcSkColorType, tempAT,
+                                        this->colorSpaceInfo().refColorSpace());
+        SkASSERT(!unpremul || !dstAlwaysOpaque);
+        auto finalAT = (srcAlwaysOpaque || dstAlwaysOpaque)
+                               ? kOpaque_SkAlphaType
+                               : unpremul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType;
+        auto finalII =
+                SkImageInfo::Make(width, height, dstSkColorType, finalAT, sk_ref_sp(dstColorSpace));
+        if (!SkImageInfoValidConversion(finalII, tempII)) {
+            return false;
+        }
+        if (!tempPixmap.tryAlloc(tempII)) {
+            return false;
+        }
+        finalPixmap.reset(finalII, buffer, rowBytes);
+        buffer = tempPixmap.writable_addr();
+        rowBytes = tempPixmap.rowBytes();
+        // Chrome msan bots require this.
+        sk_bzero(buffer, tempPixmap.computeByteSize());
     }
 
     direct->priv().flushSurface(srcProxy);
 
-    if (!direct->priv().getGpu()->readPixels(srcSurface, left, top, width, height,
-                                             supportedRead.fColorType, readDst, rowBytes)) {
+    if (!direct->priv().getGpu()->readPixels(srcSurface, left, top, width, height, allowedColorType,
+                                             buffer, rowBytes)) {
         return false;
     }
 
+    if (flip) {
+        size_t trimRowBytes = GrColorTypeBytesPerPixel(allowedColorType) * width;
+        std::unique_ptr<char[]> row(new char[trimRowBytes]);
+        char* upper = reinterpret_cast<char*>(buffer);
+        char* lower = reinterpret_cast<char*>(buffer) + (height - 1) * rowBytes;
+        for (int y = 0; y < height / 2; ++y, upper += rowBytes, lower -= rowBytes) {
+            memcpy(row.get(), upper, trimRowBytes);
+            memcpy(upper, lower, trimRowBytes);
+            memcpy(lower, row.get(), trimRowBytes);
+        }
+    }
     if (convert) {
-        return GrConvertPixels(dstInfo, buffer, tmpInfo, tmpPixels.get(), supportedRead.fSwizzle);
+        if (!tempPixmap.readPixels(finalPixmap)) {
+            return false;
+        }
     }
     return true;
 }
@@ -365,8 +383,8 @@
         // data into it which requires the origins to match. If the final proxy is a render target
         // we can use a draw instead which doesn't have this origin restriction. Thus for render
         // targets we will use top left and otherwise we will make the origins match.
-        GrSurfaceOrigin tempOrigin =
-                this->asRenderTargetContext() ? kTopLeft_GrSurfaceOrigin : dstProxy->origin();
+        GrSurfaceOrigin tempOrigin = this->asRenderTargetContext() ? kTopLeft_GrSurfaceOrigin :
+                                                                     dstProxy->origin();
         auto tempProxy = direct->priv().proxyProvider()->createProxy(
                 format, desc, tempOrigin, SkBackingFit::kApprox, SkBudgeted::kYes);
 
@@ -420,44 +438,63 @@
         return true;
     }
 
+    bool convert = premul || needColorConversion;
+
     if (!valid_pixel_conversion(srcColorType, dstProxy->config(), premul)) {
         return false;
     }
 
     GrColorType allowedColorType = caps->supportedWritePixelsColorType(dstProxy->config(),
                                                                        srcColorType);
-    bool convert = premul || needColorConversion || (srcColorType != allowedColorType) ||
-                   dstProxy->origin() == kBottomLeft_GrSurfaceOrigin;
+    convert = convert || (srcColorType != allowedColorType);
 
-    std::unique_ptr<char[]> tmpPixels;
+    std::unique_ptr<char[]> tempBuffer;
     if (convert) {
-        GrPixelInfo srcInfo;
-        srcInfo.fColorInfo.fAlphaType = (premul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType);
-        srcInfo.fColorInfo.fColorType = srcColorType;
-        srcInfo.fColorInfo.fColorSpace = srcColorSpace;
-        srcInfo.fRowBytes = srcRowBytes;
-        srcInfo.fOrigin = kTopLeft_GrSurfaceOrigin;
-
-        GrPixelInfo tmpInfo;
-        tmpInfo.fColorInfo.fAlphaType = kPremul_SkAlphaType;
-        tmpInfo.fColorInfo.fColorType = allowedColorType;
-        tmpInfo.fColorInfo.fColorSpace = this->colorSpaceInfo().colorSpace();
-        tmpInfo.fRowBytes = GrColorTypeBytesPerPixel(allowedColorType) * width;
-        tmpInfo.fOrigin = dstProxy->origin();
-
-        srcInfo.fWidth  = tmpInfo.fWidth  = width;
-        srcInfo.fHeight = tmpInfo.fHeight = height;
-
-        tmpPixels.reset(new char[tmpInfo.fRowBytes * height]);
-
-        GrConvertPixels(tmpInfo, tmpPixels.get(), srcInfo, srcBuffer);
-
-        srcColorType = tmpInfo.fColorInfo.fColorType;
-        srcBuffer = tmpPixels.get();
-        srcRowBytes = tmpInfo.fRowBytes;
+        auto srcSkColorType = GrColorTypeToSkColorType(srcColorType);
+        auto dstSkColorType = GrColorTypeToSkColorType(allowedColorType);
+        if (kUnknown_SkColorType == srcSkColorType || kUnknown_SkColorType == dstSkColorType) {
+            return false;
+        }
+        auto srcAlphaType = SkColorTypeIsAlwaysOpaque(srcSkColorType)
+                ? kOpaque_SkAlphaType
+                : (premul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType);
+        SkPixmap src(SkImageInfo::Make(width, height, srcSkColorType, srcAlphaType,
+                                       sk_ref_sp(srcColorSpace)),
+                     srcBuffer, srcRowBytes);
+        auto tempSrcII = SkImageInfo::Make(width, height, dstSkColorType, kPremul_SkAlphaType,
+                                           this->colorSpaceInfo().refColorSpace());
+        auto size = tempSrcII.computeMinByteSize();
+        if (!size) {
+            return false;
+        }
+        tempBuffer.reset(new char[size]);
+        SkPixmap tempSrc(tempSrcII, tempBuffer.get(), tempSrcII.minRowBytes());
+        if (!src.readPixels(tempSrc)) {
+            return false;
+        }
+        srcColorType = allowedColorType;
+        srcBuffer = tempSrc.addr();
+        srcRowBytes = tempSrc.rowBytes();
         if (dstProxy->origin() == kBottomLeft_GrSurfaceOrigin) {
+            std::unique_ptr<char[]> row(new char[srcRowBytes]);
+            for (int y = 0; y < height / 2; ++y) {
+                memcpy(row.get(), tempSrc.addr(0, y), srcRowBytes);
+                memcpy(tempSrc.writable_addr(0, y), tempSrc.addr(0, height - 1 - y), srcRowBytes);
+                memcpy(tempSrc.writable_addr(0, height - 1 - y), row.get(), srcRowBytes);
+            }
             top = dstSurface->height() - top - height;
         }
+    } else if (dstProxy->origin() == kBottomLeft_GrSurfaceOrigin) {
+        size_t trimRowBytes = GrColorTypeBytesPerPixel(srcColorType) * width;
+        tempBuffer.reset(new char[trimRowBytes * height]);
+        char* dst = reinterpret_cast<char*>(tempBuffer.get()) + trimRowBytes * (height - 1);
+        const char* src = reinterpret_cast<const char*>(srcBuffer);
+        for (int i = 0; i < height; ++i, src += srcRowBytes, dst -= trimRowBytes) {
+            memcpy(dst, src, trimRowBytes);
+        }
+        srcBuffer = tempBuffer.get();
+        srcRowBytes = trimRowBytes;
+        top = dstSurface->height() - top - height;
     }
 
     // On platforms that prefer flushes over VRAM use (i.e., ANGLE) we're better off forcing a
diff --git a/src/gpu/GrSwizzle.cpp b/src/gpu/GrSwizzle.cpp
index 138b24f..21fe834 100644
--- a/src/gpu/GrSwizzle.cpp
+++ b/src/gpu/GrSwizzle.cpp
@@ -11,17 +11,11 @@
 void GrSwizzle::apply(SkRasterPipeline* pipeline) const {
     SkASSERT(pipeline);
     switch (fKey) {
-        case GrSwizzle("rgba").asKey():
+        case GrSwizzle::RGBA().asKey():
             return;
-        case GrSwizzle("bgra").asKey():
+        case GrSwizzle::BGRA().asKey():
             pipeline->append(SkRasterPipeline::swap_rb);
             return;
-        case GrSwizzle("aaa1").asKey():
-            pipeline->append(SkRasterPipeline::alpha_to_gray);
-            return;
-        case GrSwizzle("rgb1").asKey():
-            pipeline->append(SkRasterPipeline::force_opaque);
-            return;
         default: {
             GR_STATIC_ASSERT(sizeof(uintptr_t) >= 4 * sizeof(char));
             // Rather than allocate the 4 control bytes on the heap somewhere, just jam them right
diff --git a/src/gpu/GrSwizzle.h b/src/gpu/GrSwizzle.h
index 991379c..cbee3eb 100644
--- a/src/gpu/GrSwizzle.h
+++ b/src/gpu/GrSwizzle.h
@@ -22,18 +22,15 @@
     constexpr GrSwizzle(const GrSwizzle&);
     constexpr GrSwizzle& operator=(const GrSwizzle& that);
 
-    static constexpr GrSwizzle Concat(const GrSwizzle& a, const GrSwizzle& b);
-
     /** Recreates a GrSwizzle from the output of asKey() */
     constexpr void setFromKey(uint16_t key);
-
     constexpr bool operator==(const GrSwizzle& that) const { return fKey == that.fKey; }
     constexpr bool operator!=(const GrSwizzle& that) const { return !(*this == that); }
 
     /** Compact representation of the swizzle suitable for a key. */
     constexpr uint16_t asKey() const { return fKey; }
 
-    /** 4 char null terminated string consisting only of chars 'r', 'g', 'b', 'a', '0', and '1'. */
+    /** 4 char null terminated string consisting only of chars 'r', 'g', 'b', 'a'. */
     constexpr const char* c_str() const { return fSwiz; }
 
     constexpr char operator[](int i) const {
@@ -58,6 +55,9 @@
     static constexpr int CToI(char c);
     static constexpr char IToC(int idx);
 
+    // The normal component swizzles map to key values 0-3. We set the key for constant 1 to the
+    // next int.
+    static const int k1KeyValue = 4;
     char fSwiz[5];
     uint16_t fKey;
 };
@@ -111,53 +111,32 @@
     if (idx <= 3) {
         return color[idx];
     }
-    if (idx == CToI('1')) {
+    if (idx == k1KeyValue) {
         return 1.0f;
     }
-    if (idx == CToI('0')) {
-        return 1.0f;
-    }
-    SkASSERT(false);
     return -1.0f;
 }
 
 constexpr int GrSwizzle::CToI(char c) {
     switch (c) {
-        // r...a must map to 0...3 because other methods use them as indices into fSwiz.
-        case 'r': return 0;
-        case 'g': return 1;
-        case 'b': return 2;
-        case 'a': return 3;
-        case '0': return 4;
-        case '1': return 5;
-        default:  SkASSERT(false);
+        case 'r': return (GrColor_SHIFT_R / 8);
+        case 'g': return (GrColor_SHIFT_G / 8);
+        case 'b': return (GrColor_SHIFT_B / 8);
+        case 'a': return (GrColor_SHIFT_A / 8);
+        case '1': return k1KeyValue;
+        default:  return -1;
     }
-    return -1;
 }
 
 constexpr char GrSwizzle::IToC(int idx) {
-    switch (idx) {
-        case CToI('r'): return 'r';
-        case CToI('g'): return 'g';
-        case CToI('b'): return 'b';
-        case CToI('a'): return 'a';
-        case CToI('0'): return '0';
-        case CToI('1'): return '1';
-        default:        SkASSERT(false);
+    switch (8 * idx) {
+        case GrColor_SHIFT_R  : return 'r';
+        case GrColor_SHIFT_G  : return 'g';
+        case GrColor_SHIFT_B  : return 'b';
+        case GrColor_SHIFT_A  : return 'a';
+        case (k1KeyValue * 8) : return '1';
+        default:                return -1;
     }
-    return -1;
 }
 
-constexpr GrSwizzle GrSwizzle::Concat(const GrSwizzle& a, const GrSwizzle& b) {
-    char swiz[4]{};
-    for (int i = 0; i < 4; ++i) {
-        int idx = (b.fKey >> (4U * i)) & 0xfU;
-        switch (idx) {
-            case CToI('0'): swiz[i] = '0';          break;
-            case CToI('1'): swiz[i] = '1';          break;
-            default:        swiz[i] = a.fSwiz[idx]; break;
-        }
-    }
-    return GrSwizzle(swiz);
-}
 #endif
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 3495383..462ead8 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -1333,6 +1333,13 @@
     bool surfaceIsAlphaOnly = GrPixelConfigIsAlphaOnly(surfaceConfig);
     bool memoryIsAlphaOnly = GrPixelConfigIsAlphaOnly(memoryConfig);
 
+    // We don't currently support moving RGBA data into and out of ALPHA surfaces. It could be
+    // made to work. However, this is complicated by the use of GL_RED for alpha-only textures but
+    // is not needed currently.
+    if (surfaceIsAlphaOnly && !memoryIsAlphaOnly) {
+        return false;
+    }
+
     *externalFormat = fConfigTable[memoryConfig].fFormats.fExternalFormat[usage];
     *externalType = fConfigTable[memoryConfig].fFormats.fExternalType;
 
@@ -1548,7 +1555,9 @@
     fConfigTable[kRGB_888_GrPixelConfig].fFormats.fSizedInternalFormat = GR_GL_RGB8;
     // Our external RGB data always has a byte where alpha would be. When calling read pixels we
     // want to read to kRGB_888x color type and ensure that gets 0xFF written. Using GL_RGB would
-    // read back unaligned 24bit RGB color values.
+    // read back unaligned 24bit RGB color values. Note that this all a bit moot as we don't
+    // currently expect to ever read back GrColorType::kRGB_888x because our implementation of
+    // supportedReadPixelsColorType never returns it.
     fConfigTable[kRGB_888_GrPixelConfig].fFormats.fExternalFormat[kReadPixels_ExternalFormatUsage] = GR_GL_RGBA;
     fConfigTable[kRGB_888_GrPixelConfig].fFormats.fExternalType = GR_GL_UNSIGNED_BYTE;
     fConfigTable[kRGB_888_GrPixelConfig].fFormatType = kNormalizedFixedPoint_FormatType;
@@ -1839,7 +1848,6 @@
     alphaInfo.fFormats.fSizedInternalFormat = GR_GL_ALPHA8;
     alphaInfo.fFormats.fExternalFormat[kReadPixels_ExternalFormatUsage] = GR_GL_ALPHA;
     shaderCaps->fConfigTextureSwizzle[kAlpha_8_as_Alpha_GrPixelConfig] = GrSwizzle::AAAA();
-    alphaInfo.fRGBAReadSwizzle = GrSwizzle("000a");
     if (fAlpha8IsRenderable && alpha8IsValidForGL) {
         alphaInfo.fFlags |= allRenderFlags;
     }
@@ -1850,7 +1858,6 @@
     redInfo.fFormats.fExternalFormat[kReadPixels_ExternalFormatUsage] = GR_GL_RED;
     redInfo.fFormats.fExternalType = GR_GL_UNSIGNED_BYTE;
     redInfo.fFormatType = kNormalizedFixedPoint_FormatType;
-    redInfo.fRGBAReadSwizzle = GrSwizzle("000r");
     shaderCaps->fConfigTextureSwizzle[kAlpha_8_as_Red_GrPixelConfig] = GrSwizzle::RRRR();
 
     // ES2 Command Buffer does not allow TexStorage with R8_EXT (so Alpha_8 and Gray_8)
@@ -2035,7 +2042,6 @@
     redHalf.fFormats.fSizedInternalFormat = GR_GL_R16F;
     redHalf.fFormats.fExternalFormat[kReadPixels_ExternalFormatUsage] = GR_GL_RED;
     shaderCaps->fConfigTextureSwizzle[kAlpha_half_as_Red_GrPixelConfig] = GrSwizzle::RRRR();
-    redHalf.fRGBAReadSwizzle = GrSwizzle("000r");
     if (textureRedSupport && hasFP16Textures) {
         redHalf.fFlags = ConfigInfo::kTextureable_Flag;
 
@@ -3027,29 +3033,30 @@
     return true;
 }
 
-GrCaps::SupportedRead GrGLCaps::supportedReadPixelsColorType(GrPixelConfig srcPixelConfig,
-                                                             const GrBackendFormat& srcFormat,
-                                                             GrColorType dstColorType) const {
+GrColorType GrGLCaps::supportedReadPixelsColorType(GrPixelConfig config,
+                                                   GrColorType dstColorType) const {
     // For now, we mostly report the read back format that is required by the ES spec without
     // checking for implementation allowed formats or consider laxer rules in non-ES GL. TODO: Relax
     // this as makes sense to increase performance and correctness.
-    const GrGLenum* glFormat = srcFormat.getGLFormat();
-    if (!glFormat) {
-        return {GrSwizzle{}, GrColorType::kUnknown};
-    }
-    auto swizzle = fConfigTable[srcPixelConfig].fRGBAReadSwizzle;
-    switch (fConfigTable[srcPixelConfig].fFormatType) {
+    switch (fConfigTable[config].fFormatType) {
         case kNormalizedFixedPoint_FormatType:
-            if (kRGB_888X_GrPixelConfig == srcPixelConfig && *glFormat == GR_GL_RGBA8 &&
-                GrColorTypeHasAlpha(dstColorType)) {
-                // This can skip an unnecessary conversion.
-                return {swizzle, GrColorType::kRGB_888x};
+            if (kRGB_888X_GrPixelConfig == config) {
+                return GrColorType::kRGB_888x;
             }
-            return {swizzle, GrColorType::kRGBA_8888};
+            return GrColorType::kRGBA_8888;
         case kFloat_FormatType:
-            return {swizzle, GrColorType::kRGBA_F32};
+            if ((kAlpha_half_GrPixelConfig == config ||
+                 kAlpha_half_as_Red_GrPixelConfig == config) &&
+                GrColorType::kAlpha_F16 == dstColorType) {
+                return GrColorType::kAlpha_F16;
+            }
+            // And similar for full float RG.
+            if (kRG_float_GrPixelConfig == config && GrColorType::kRG_F32 == dstColorType) {
+                return GrColorType::kRG_F32;
+            }
+            return GrColorType::kRGBA_F32;
     }
-    return {GrSwizzle{}, GrColorType::kUnknown};
+    return GrColorType::kUnknown;
 }
 
 bool GrGLCaps::onIsWindowRectanglesSupportedForRT(const GrBackendRenderTarget& backendRT) const {
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index 54cc1d9..fe1a9f2 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -307,8 +307,7 @@
     bool useNonVBOVertexAndIndexDynamicData() const { return fUseNonVBOVertexAndIndexDynamicData; }
 
     bool surfaceSupportsReadPixels(const GrSurface*) const override;
-    SupportedRead supportedReadPixelsColorType(GrPixelConfig, const GrBackendFormat&,
-                                               GrColorType) const override;
+    GrColorType supportedReadPixelsColorType(GrPixelConfig, GrColorType) const override;
 
     /// Does ReadPixels support reading readConfig pixels from a FBO that is surfaceConfig?
     bool readPixelsSupported(GrPixelConfig surfaceConfig,
@@ -569,11 +568,6 @@
         // Index fStencilFormats.
         int fStencilFormatIndex;
 
-        // If data from a surface of this config is read back to a GrColorType with all four
-        // color channels this indicates how each channel should be interpreted. May contain
-        // 0s and 1s.
-        GrSwizzle fRGBAReadSwizzle = GrSwizzle("rgba");
-
         SkTDArray<int> fColorSampleCounts;
 
         enum {
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 8aa6bb4..811b718 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -2973,7 +2973,6 @@
             case 'g': glValues[i] = GR_GL_GREEN; break;
             case 'b': glValues[i] = GR_GL_BLUE;  break;
             case 'a': glValues[i] = GR_GL_ALPHA; break;
-            case '0': glValues[i] = GR_GL_ZERO;  break;
             case '1': glValues[i] = GR_GL_ONE;   break;
             default:  SK_ABORT("Unsupported component");
         }
diff --git a/src/opts/SkRasterPipeline_opts.h b/src/opts/SkRasterPipeline_opts.h
index f2a802a..6689066 100644
--- a/src/opts/SkRasterPipeline_opts.h
+++ b/src/opts/SkRasterPipeline_opts.h
@@ -2624,7 +2624,6 @@
             case 'g': *o[i] = ig;   break;
             case 'b': *o[i] = ib;   break;
             case 'a': *o[i] = ia;   break;
-            case '0': *o[i] = F(0); break;
             case '1': *o[i] = F(1); break;
             default:                break;
         }
@@ -3430,7 +3429,7 @@
 
 STAGE_PP(load_rg88, const SkRasterPipeline_MemoryCtx* ctx) {
     b = 0;
-    a = 255;
+    a = 1;
     load_88_(ptr_at_xy<const uint16_t>(ctx, dx,dy), tail, &r,&g);
 }
 STAGE_PP(store_rg88, const SkRasterPipeline_MemoryCtx* ctx) {
@@ -3821,7 +3820,6 @@
             case 'g': *o[i] = ig;       break;
             case 'b': *o[i] = ib;       break;
             case 'a': *o[i] = ia;       break;
-            case '0': *o[i] = U16(0);   break;
             case '1': *o[i] = U16(255); break;
             default:                    break;
         }