Plumb GrColorType through all ops/processors that sample textures.

This change also allows for the remove of GrPixelConfigIsOpaque function.

Bug: skia:6718
Change-Id: I7e7b70f02d911eda67640d648fb6348091e0f55d
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/248698
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
diff --git a/gm/clockwise.cpp b/gm/clockwise.cpp
index 78b1da8..f16e45a 100644
--- a/gm/clockwise.cpp
+++ b/gm/clockwise.cpp
@@ -196,14 +196,15 @@
     rtc->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, true, 100));
 
     // Draw the test to an off-screen, top-down render target.
+    GrColorType rtcColorType = rtc->colorInfo().colorType();
     if (auto topLeftRTC = ctx->priv().makeDeferredRenderTargetContext(
-                SkBackingFit::kExact, 100, 200, rtc->colorInfo().colorType(), nullptr, 1,
+                SkBackingFit::kExact, 100, 200, rtcColorType, nullptr, 1,
                 GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin, nullptr, SkBudgeted::kYes)) {
         topLeftRTC->clear(nullptr, SK_PMColor4fTRANSPARENT,
                           GrRenderTargetContext::CanClearFullscreen::kYes);
         topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, false, 0));
         topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, true, 100));
-        rtc->drawTexture(GrNoClip(), sk_ref_sp(topLeftRTC->asTextureProxy()),
+        rtc->drawTexture(GrNoClip(), sk_ref_sp(topLeftRTC->asTextureProxy()), rtcColorType,
                          GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver,
                          SK_PMColor4fWHITE, {0, 0, 100, 200},
                          {100, 0, 200, 200}, GrAA::kNo, GrQuadAAFlags::kNone,
@@ -213,13 +214,13 @@
 
     // Draw the test to an off-screen, bottom-up render target.
     if (auto topLeftRTC = ctx->priv().makeDeferredRenderTargetContext(
-                SkBackingFit::kExact, 100, 200, rtc->colorInfo().colorType(), nullptr, 1,
+                SkBackingFit::kExact, 100, 200, rtcColorType, nullptr, 1,
                 GrMipMapped::kNo, kBottomLeft_GrSurfaceOrigin, nullptr, SkBudgeted::kYes)) {
         topLeftRTC->clear(nullptr, SK_PMColor4fTRANSPARENT,
                           GrRenderTargetContext::CanClearFullscreen::kYes);
         topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, false, 0));
         topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, true, 100));
-        rtc->drawTexture(GrNoClip(), sk_ref_sp(topLeftRTC->asTextureProxy()),
+        rtc->drawTexture(GrNoClip(), sk_ref_sp(topLeftRTC->asTextureProxy()), rtcColorType,
                          GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver,
                          SK_PMColor4fWHITE, {0, 0, 100, 200},
                          {200, 0, 300, 200}, GrAA::kNo, GrQuadAAFlags::kNone,
diff --git a/gm/fpcoordinateoverride.cpp b/gm/fpcoordinateoverride.cpp
index 721a783..212fd25 100644
--- a/gm/fpcoordinateoverride.cpp
+++ b/gm/fpcoordinateoverride.cpp
@@ -83,8 +83,10 @@
     SkBitmap bmp;
     GetResourceAsBitmap("images/mandrill_512_q075.jpg", &bmp);
     GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
+    GrColorType srcColorType = SkColorTypeToGrColorType(bmp.colorType());
     sk_sp<GrTextureProxy> texture = proxyProvider->createProxyFromBitmap(bmp, GrMipMapped::kNo);
-    std::unique_ptr<GrFragmentProcessor> imgFP = GrSimpleTextureEffect::Make(texture, SkMatrix());
+    std::unique_ptr<GrFragmentProcessor> imgFP = GrSimpleTextureEffect::Make(texture, srcColorType,
+                                                                             SkMatrix());
     auto fp = std::unique_ptr<GrFragmentProcessor>(new SampleCoordEffect(std::move(imgFP)));
 
     GrPaint grPaint;
diff --git a/gm/image_pict.cpp b/gm/image_pict.cpp
index f916ca7..e637bc5 100644
--- a/gm/image_pict.cpp
+++ b/gm/image_pict.cpp
@@ -198,7 +198,8 @@
 
         GrMipMapped mipMapped = willBeMipped ? GrMipMapped::kYes : GrMipMapped::kNo;
 
-        return GrSurfaceProxy::Copy(fCtx.get(), fProxy.get(), mipMapped,
+        return GrSurfaceProxy::Copy(fCtx.get(), fProxy.get(),
+                SkColorTypeToGrColorType(info.colorType()), mipMapped,
                 SkIRect::MakeXYWH(origin.x(), origin.y(), info.width(), info.height()),
                 SkBackingFit::kExact, SkBudgeted::kYes);
     }
diff --git a/gm/samplelocations.cpp b/gm/samplelocations.cpp
index 7e48f15..eeba571 100644
--- a/gm/samplelocations.cpp
+++ b/gm/samplelocations.cpp
@@ -310,9 +310,10 @@
     // Copy offscreen texture to canvas.
     rtc->drawTexture(
             GrNoClip(), sk_ref_sp(offscreenRTC->asTextureProxy()),
-            GrSamplerState::Filter::kNearest, SkBlendMode::kSrc, SK_PMColor4fWHITE,
-            {0,0,200,200}, {0,0,200,200}, GrAA::kNo, GrQuadAAFlags::kNone,
-            SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, SkMatrix::I(), nullptr);
+            offscreenRTC->colorInfo().colorType(), GrSamplerState::Filter::kNearest,
+            SkBlendMode::kSrc, SK_PMColor4fWHITE, {0,0,200,200}, {0,0,200,200}, GrAA::kNo,
+            GrQuadAAFlags::kNone, SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint,
+            SkMatrix::I(), nullptr);
 
     return skiagm::DrawResult::kOk;
 }
diff --git a/gm/texturedomaineffect.cpp b/gm/texturedomaineffect.cpp
index b30079f..5355e2e 100644
--- a/gm/texturedomaineffect.cpp
+++ b/gm/texturedomaineffect.cpp
@@ -142,7 +142,8 @@
                     GrPaint grPaint;
                     grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
                     auto fp = GrTextureDomainEffect::Make(
-                            proxy, textureMatrices[tm],
+                            proxy, SkColorTypeToGrColorType(fBitmap.colorType()),
+                            textureMatrices[tm],
                             GrTextureDomain::MakeTexelDomain(texelDomains[d], mode),
                             mode, fFilter);
 
diff --git a/include/private/GrTypesPriv.h b/include/private/GrTypesPriv.h
index 019bf35..eca0a2d 100644
--- a/include/private/GrTypesPriv.h
+++ b/include/private/GrTypesPriv.h
@@ -813,40 +813,6 @@
     SkUNREACHABLE;
 }
 
-static constexpr bool GrPixelConfigIsOpaque(GrPixelConfig config) {
-    switch (config) {
-        case kRGB_565_GrPixelConfig:
-        case kRGB_888_GrPixelConfig:
-        case kRGB_888X_GrPixelConfig:
-        case kRG_88_GrPixelConfig:
-        case kGray_8_GrPixelConfig:
-        case kGray_8_as_Lum_GrPixelConfig:
-        case kGray_8_as_Red_GrPixelConfig:
-        case kRGB_ETC1_GrPixelConfig:
-        case kRG_1616_GrPixelConfig:
-        case kRG_half_GrPixelConfig:
-            return true;
-        case kAlpha_8_GrPixelConfig:
-        case kAlpha_8_as_Alpha_GrPixelConfig:
-        case kAlpha_8_as_Red_GrPixelConfig:
-        case kAlpha_16_GrPixelConfig:
-        case kRGBA_4444_GrPixelConfig:
-        case kAlpha_half_GrPixelConfig:
-        case kAlpha_half_as_Lum_GrPixelConfig:
-        case kAlpha_half_as_Red_GrPixelConfig:
-        case kRGBA_8888_GrPixelConfig:
-        case kBGRA_8888_GrPixelConfig:
-        case kSRGBA_8888_GrPixelConfig:
-        case kRGBA_1010102_GrPixelConfig:
-        case kRGBA_half_GrPixelConfig:
-        case kRGBA_half_Clamped_GrPixelConfig:
-        case kRGBA_16161616_GrPixelConfig:
-        case kUnknown_GrPixelConfig:
-            return false;
-    }
-    SkUNREACHABLE;
-}
-
 /**
  * Returns true if the pixel config is a GPU-specific compressed format
  * representation.
diff --git a/samplecode/SampleCCPRGeometry.cpp b/samplecode/SampleCCPRGeometry.cpp
index 56e9df2..2f70ff2 100644
--- a/samplecode/SampleCCPRGeometry.cpp
+++ b/samplecode/SampleCCPRGeometry.cpp
@@ -195,7 +195,8 @@
         // Visualize coverage count in main canvas.
         GrPaint paint;
         paint.addColorFragmentProcessor(
-                GrSimpleTextureEffect::Make(sk_ref_sp(ccbuff->asTextureProxy()), SkMatrix::I()));
+                GrSimpleTextureEffect::Make(sk_ref_sp(ccbuff->asTextureProxy()),
+                                            ccbuff->colorInfo().colorType(), SkMatrix::I()));
         paint.addColorFragmentProcessor(
                 skstd::make_unique<VisualizeCoverageCountFP>());
         paint.setPorterDuffXPFactory(SkBlendMode::kSrcOver);
diff --git a/src/core/SkBlurMF.cpp b/src/core/SkBlurMF.cpp
index 4464dea..d385af8 100644
--- a/src/core/SkBlurMF.cpp
+++ b/src/core/SkBlurMF.cpp
@@ -902,6 +902,7 @@
         GrPaint paint;
         // Blend pathTexture over blurTexture.
         paint.addCoverageFragmentProcessor(GrSimpleTextureEffect::Make(std::move(srcProxy),
+                                                                       srcColorType,
                                                                        SkMatrix::I()));
         if (kInner_SkBlurStyle == fBlurStyle) {
             // inner:  dst = dst * src
diff --git a/src/core/SkGpuBlurUtils.cpp b/src/core/SkGpuBlurUtils.cpp
index b7371f5..c863908 100644
--- a/src/core/SkGpuBlurUtils.cpp
+++ b/src/core/SkGpuBlurUtils.cpp
@@ -76,6 +76,7 @@
                                  const SkIRect& dstRect,
                                  const SkIPoint& srcOffset,
                                  sk_sp<GrTextureProxy> proxy,
+                                 GrColorType srcColorType,
                                  Direction direction,
                                  int radius,
                                  float sigma,
@@ -83,7 +84,7 @@
                                  int bounds[2]) {
     GrPaint paint;
     std::unique_ptr<GrFragmentProcessor> conv(GrGaussianConvolutionFragmentProcessor::Make(
-            std::move(proxy), direction, radius, sigma, mode, bounds));
+            std::move(proxy), srcColorType, direction, radius, sigma, mode, bounds));
     paint.addColorFragmentProcessor(std::move(conv));
     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
     SkMatrix localMatrix = SkMatrix::MakeTrans(-SkIntToScalar(srcOffset.x()),
@@ -189,7 +190,7 @@
     if (GrTextureDomain::kIgnore_Mode == mode) {
         *contentRect = dstRect;
         convolve_gaussian_1d(dstRenderTargetContext.get(), clip, dstRect, netOffset,
-                             std::move(srcProxy), direction, radius, sigma,
+                             std::move(srcProxy), srcColorType, direction, radius, sigma,
                              GrTextureDomain::kIgnore_Mode, bounds);
         return dstRenderTargetContext;
     }
@@ -244,15 +245,16 @@
     if (midRect.isEmpty()) {
         // Blur radius covers srcBounds; use bounds over entire draw
         convolve_gaussian_1d(dstRenderTargetContext.get(), clip, dstRect, netOffset,
-                             std::move(srcProxy), direction, radius, sigma, mode, bounds);
+                             std::move(srcProxy), srcColorType, direction, radius, sigma, mode,
+                             bounds);
     } else {
         // Draw right and left margins with bounds; middle without.
         convolve_gaussian_1d(dstRenderTargetContext.get(), clip, leftRect, netOffset,
-                             srcProxy, direction, radius, sigma, mode, bounds);
+                             srcProxy, srcColorType, direction, radius, sigma, mode, bounds);
         convolve_gaussian_1d(dstRenderTargetContext.get(), clip, rightRect, netOffset,
-                             srcProxy, direction, radius, sigma, mode, bounds);
+                             srcProxy, srcColorType, direction, radius, sigma, mode, bounds);
         convolve_gaussian_1d(dstRenderTargetContext.get(), clip, midRect, netOffset,
-                             std::move(srcProxy), direction, radius, sigma,
+                             std::move(srcProxy), srcColorType, direction, radius, sigma,
                              GrTextureDomain::kIgnore_Mode, bounds);
     }
 
@@ -334,6 +336,7 @@
             }
             domain.offset(proxyOffset.x(), proxyOffset.y());
             auto fp = GrTextureDomainEffect::Make(std::move(srcProxy),
+                                                  srcColorType,
                                                   SkMatrix::I(),
                                                   domain,
                                                   modeForScaling,
@@ -344,7 +347,7 @@
             // back in GaussianBlur
             srcOffset->set(0, 0);
         } else {
-            paint.addColorTextureProcessor(std::move(srcProxy), SkMatrix::I(),
+            paint.addColorTextureProcessor(std::move(srcProxy), srcColorType, SkMatrix::I(),
                                            GrSamplerState::ClampBilerp());
         }
         paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
@@ -401,7 +404,7 @@
     GrPaint paint;
     SkRect domain = GrTextureDomain::MakeTexelDomain(localSrcBounds, GrTextureDomain::kClamp_Mode,
                                                      GrTextureDomain::kClamp_Mode);
-    auto fp = GrTextureDomainEffect::Make(std::move(srcProxy), SkMatrix::I(), domain,
+    auto fp = GrTextureDomainEffect::Make(std::move(srcProxy), srcColorType, SkMatrix::I(), domain,
                                           GrTextureDomain::kClamp_Mode,
                                           GrSamplerState::Filter::kBilerp);
     paint.addColorFragmentProcessor(std::move(fp));
diff --git a/src/core/SkSpecialImage.cpp b/src/core/SkSpecialImage.cpp
index 8995196..3c72e61 100644
--- a/src/core/SkSpecialImage.cpp
+++ b/src/core/SkSpecialImage.cpp
@@ -501,8 +501,9 @@
             }
 
             sk_sp<GrTextureProxy> subsetProxy(
-                    GrSurfaceProxy::Copy(fContext, fTextureProxy.get(), GrMipMapped::kNo, *subset,
-                                         SkBackingFit::kExact, SkBudgeted::kYes));
+                    GrSurfaceProxy::Copy(fContext, fTextureProxy.get(), fColorType,
+                                         GrMipMapped::kNo, *subset, SkBackingFit::kExact,
+                                         SkBudgeted::kYes));
             if (!subsetProxy) {
                 return nullptr;
             }
diff --git a/src/effects/imagefilters/SkAlphaThresholdFilter.cpp b/src/effects/imagefilters/SkAlphaThresholdFilter.cpp
index a9337a0..a059b65 100644
--- a/src/effects/imagefilters/SkAlphaThresholdFilter.cpp
+++ b/src/effects/imagefilters/SkAlphaThresholdFilter.cpp
@@ -166,7 +166,8 @@
             return nullptr;
         }
 
-        auto textureFP = GrSimpleTextureEffect::Make(std::move(inputProxy),
+        GrColorType srcColorType = SkColorTypeToGrColorType(input->colorType());
+        auto textureFP = GrSimpleTextureEffect::Make(std::move(inputProxy), srcColorType,
                                                      SkMatrix::MakeTrans(input->subset().x(),
                                                                          input->subset().y()));
         textureFP = GrColorSpaceXformEffect::Make(std::move(textureFP), input->getColorSpace(),
diff --git a/src/effects/imagefilters/SkArithmeticImageFilter.cpp b/src/effects/imagefilters/SkArithmeticImageFilter.cpp
index 1da9be1..2b1aaaf 100644
--- a/src/effects/imagefilters/SkArithmeticImageFilter.cpp
+++ b/src/effects/imagefilters/SkArithmeticImageFilter.cpp
@@ -353,8 +353,9 @@
         SkMatrix backgroundMatrix = SkMatrix::MakeTrans(
                 SkIntToScalar(bgSubset.left() - backgroundOffset.fX),
                 SkIntToScalar(bgSubset.top()  - backgroundOffset.fY));
+        GrColorType bgColorType = SkColorTypeToGrColorType(background->colorType());
         bgFP = GrTextureDomainEffect::Make(
-                std::move(backgroundProxy), backgroundMatrix,
+                std::move(backgroundProxy), bgColorType, backgroundMatrix,
                 GrTextureDomain::MakeTexelDomain(bgSubset, GrTextureDomain::kDecal_Mode),
                 GrTextureDomain::kDecal_Mode, GrSamplerState::Filter::kNearest);
         bgFP = GrColorSpaceXformEffect::Make(std::move(bgFP), background->getColorSpace(),
@@ -370,8 +371,9 @@
         SkMatrix foregroundMatrix = SkMatrix::MakeTrans(
                 SkIntToScalar(fgSubset.left() - foregroundOffset.fX),
                 SkIntToScalar(fgSubset.top()  - foregroundOffset.fY));
+        GrColorType fgColorType = SkColorTypeToGrColorType(foreground->colorType());
         auto foregroundFP = GrTextureDomainEffect::Make(
-                std::move(foregroundProxy), foregroundMatrix,
+                std::move(foregroundProxy), fgColorType, foregroundMatrix,
                 GrTextureDomain::MakeTexelDomain(fgSubset, GrTextureDomain::kDecal_Mode),
                 GrTextureDomain::kDecal_Mode, GrSamplerState::Filter::kNearest);
         foregroundFP = GrColorSpaceXformEffect::Make(std::move(foregroundFP),
diff --git a/src/effects/imagefilters/SkMorphologyImageFilter.cpp b/src/effects/imagefilters/SkMorphologyImageFilter.cpp
index bd9ee7f..3fa7eb1 100644
--- a/src/effects/imagefilters/SkMorphologyImageFilter.cpp
+++ b/src/effects/imagefilters/SkMorphologyImageFilter.cpp
@@ -210,18 +210,20 @@
 class GrMorphologyEffect : public GrFragmentProcessor {
 public:
     static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
+                                                     GrColorType srcColorType,
                                                      MorphDirection dir,
                                                      int radius, MorphType type) {
         return std::unique_ptr<GrFragmentProcessor>(
-                new GrMorphologyEffect(std::move(proxy), dir, radius, type, nullptr));
+                new GrMorphologyEffect(std::move(proxy), srcColorType, dir, radius, type, nullptr));
     }
 
     static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
+                                                     GrColorType srcColorType,
                                                      MorphDirection dir,
                                                      int radius, MorphType type,
                                                      const float bounds[2]) {
         return std::unique_ptr<GrFragmentProcessor>(
-                new GrMorphologyEffect(std::move(proxy), dir, radius, type, bounds));
+                new GrMorphologyEffect(std::move(proxy), srcColorType, dir, radius, type, bounds));
     }
 
     MorphType type() const { return fType; }
@@ -254,8 +256,8 @@
 
     const TextureSampler& onTextureSampler(int i) const override { return fTextureSampler; }
 
-    GrMorphologyEffect(sk_sp<GrTextureProxy>, MorphDirection, int radius, MorphType,
-                       const float range[2]);
+    GrMorphologyEffect(sk_sp<GrTextureProxy>, GrColorType srcColorType, MorphDirection, int radius,
+                       MorphType, const float range[2]);
     explicit GrMorphologyEffect(const GrMorphologyEffect&);
 
     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
@@ -393,12 +395,13 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 GrMorphologyEffect::GrMorphologyEffect(sk_sp<GrTextureProxy> proxy,
+                                       GrColorType srcColorType,
                                        MorphDirection direction,
                                        int radius,
                                        MorphType type,
                                        const float range[2])
         : INHERITED(kGrMorphologyEffect_ClassID,
-                    ModulateForClampedSamplerOptFlags(proxy->config()))
+                    ModulateForClampedSamplerOptFlags(srcColorType))
         , fCoordTransform(proxy.get())
         , fTextureSampler(std::move(proxy))
         , fDirection(direction)
@@ -463,13 +466,15 @@
     int radius = d->fRandom->nextRangeU(1, kMaxRadius);
     MorphType type = d->fRandom->nextBool() ? MorphType::kErode : MorphType::kDilate;
 
-    return GrMorphologyEffect::Make(std::move(proxy), dir, radius, type);
+    return GrMorphologyEffect::Make(std::move(proxy), d->textureProxyColorType(texIdx), dir, radius,
+                                    type);
 }
 #endif
 
 static void apply_morphology_rect(GrRenderTargetContext* renderTargetContext,
                                   const GrClip& clip,
                                   sk_sp<GrTextureProxy> proxy,
+                                  GrColorType srcColorType,
                                   const SkIRect& srcRect,
                                   const SkIRect& dstRect,
                                   int radius,
@@ -477,7 +482,7 @@
                                   const float bounds[2],
                                   MorphDirection direction) {
     GrPaint paint;
-    paint.addColorFragmentProcessor(GrMorphologyEffect::Make(std::move(proxy),
+    paint.addColorFragmentProcessor(GrMorphologyEffect::Make(std::move(proxy), srcColorType,
                                                              direction, radius, morphType,
                                                              bounds));
     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
@@ -488,13 +493,14 @@
 static void apply_morphology_rect_no_bounds(GrRenderTargetContext* renderTargetContext,
                                             const GrClip& clip,
                                             sk_sp<GrTextureProxy> proxy,
+                                            GrColorType srcColorType,
                                             const SkIRect& srcRect,
                                             const SkIRect& dstRect,
                                             int radius,
                                             MorphType morphType,
                                             MorphDirection direction) {
     GrPaint paint;
-    paint.addColorFragmentProcessor(GrMorphologyEffect::Make(std::move(proxy),
+    paint.addColorFragmentProcessor(GrMorphologyEffect::Make(std::move(proxy), srcColorType,
                                                              direction, radius, morphType));
     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
     renderTargetContext->fillRectToRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(),
@@ -504,6 +510,7 @@
 static void apply_morphology_pass(GrRenderTargetContext* renderTargetContext,
                                   const GrClip& clip,
                                   sk_sp<GrTextureProxy> textureProxy,
+                                  GrColorType srcColorType,
                                   const SkIRect& srcRect,
                                   const SkIRect& dstRect,
                                   int radius,
@@ -534,16 +541,17 @@
     }
     if (middleSrcRect.width() <= 0) {
         // radius covers srcRect; use bounds over entire draw
-        apply_morphology_rect(renderTargetContext, clip, std::move(textureProxy),
+        apply_morphology_rect(renderTargetContext, clip, std::move(textureProxy), srcColorType,
                               srcRect, dstRect, radius, morphType, bounds, direction);
     } else {
         // Draw upper and lower margins with bounds; middle without.
-        apply_morphology_rect(renderTargetContext, clip, textureProxy,
+        apply_morphology_rect(renderTargetContext, clip, textureProxy, srcColorType,
                               lowerSrcRect, lowerDstRect, radius, morphType, bounds, direction);
-        apply_morphology_rect(renderTargetContext, clip, textureProxy,
+        apply_morphology_rect(renderTargetContext, clip, textureProxy, srcColorType,
                               upperSrcRect, upperDstRect, radius, morphType, bounds, direction);
         apply_morphology_rect_no_bounds(renderTargetContext, clip, std::move(textureProxy),
-                                        middleSrcRect, middleDstRect, radius, morphType, direction);
+                                        srcColorType, middleSrcRect, middleDstRect, radius,
+                                        morphType, direction);
     }
 }
 
@@ -551,6 +559,7 @@
         GrRecordingContext* context, SkSpecialImage* input, const SkIRect& rect,
         MorphType morphType, SkISize radius, const SkImageFilter_Base::Context& ctx) {
     sk_sp<GrTextureProxy> srcTexture(input->asTextureProxyRef(context));
+    GrColorType srcColorType = SkColorTypeToGrColorType(input->colorType());
     SkASSERT(srcTexture);
     sk_sp<SkColorSpace> colorSpace = ctx.refColorSpace();
     GrColorType colorType = ctx.grColorType();
@@ -581,8 +590,8 @@
             return nullptr;
         }
 
-        apply_morphology_pass(dstRTContext.get(), clip, std::move(srcTexture), srcRect, dstRect,
-                              radius.fWidth, morphType, MorphDirection::kX);
+        apply_morphology_pass(dstRTContext.get(), clip, std::move(srcTexture), srcColorType,
+                              srcRect, dstRect, radius.fWidth, morphType, MorphDirection::kX);
         SkIRect clearRect = SkIRect::MakeXYWH(dstRect.fLeft, dstRect.fBottom,
                                               dstRect.width(), radius.fHeight);
         SkPMColor4f clearColor = MorphType::kErode == morphType
@@ -590,6 +599,7 @@
         dstRTContext->clear(&clearRect, clearColor, GrRenderTargetContext::CanClearFullscreen::kNo);
 
         srcTexture = dstRTContext->asTextureProxyRef();
+        srcColorType = colorType;
         srcRect = dstRect;
     }
     if (radius.fHeight > 0) {
@@ -609,8 +619,8 @@
             return nullptr;
         }
 
-        apply_morphology_pass(dstRTContext.get(), clip, std::move(srcTexture), srcRect, dstRect,
-                              radius.fHeight, morphType, MorphDirection::kY);
+        apply_morphology_pass(dstRTContext.get(), clip, std::move(srcTexture), srcColorType,
+                              srcRect, dstRect, radius.fHeight, morphType, MorphDirection::kY);
 
         srcTexture = dstRTContext->asTextureProxyRef();
     }
diff --git a/src/effects/imagefilters/SkXfermodeImageFilter.cpp b/src/effects/imagefilters/SkXfermodeImageFilter.cpp
index 8b2e5d6..14cf52f 100644
--- a/src/effects/imagefilters/SkXfermodeImageFilter.cpp
+++ b/src/effects/imagefilters/SkXfermodeImageFilter.cpp
@@ -266,8 +266,9 @@
         SkMatrix bgMatrix = SkMatrix::MakeTrans(
                 SkIntToScalar(bgSubset.left() - backgroundOffset.fX),
                 SkIntToScalar(bgSubset.top()  - backgroundOffset.fY));
+        GrColorType bgColorType = SkColorTypeToGrColorType(background->colorType());
         bgFP = GrTextureDomainEffect::Make(
-                    std::move(backgroundProxy), bgMatrix,
+                    std::move(backgroundProxy), bgColorType, bgMatrix,
                     GrTextureDomain::MakeTexelDomain(bgSubset, GrTextureDomain::kDecal_Mode),
                     GrTextureDomain::kDecal_Mode, GrSamplerState::Filter::kNearest);
         bgFP = GrColorSpaceXformEffect::Make(std::move(bgFP), background->getColorSpace(),
@@ -283,8 +284,9 @@
         SkMatrix fgMatrix = SkMatrix::MakeTrans(
                 SkIntToScalar(fgSubset.left() - foregroundOffset.fX),
                 SkIntToScalar(fgSubset.top()  - foregroundOffset.fY));
+        GrColorType fgColorType = SkColorTypeToGrColorType(foreground->colorType());
         auto foregroundFP = GrTextureDomainEffect::Make(
-                std::move(foregroundProxy), fgMatrix,
+                std::move(foregroundProxy), fgColorType, fgMatrix,
                 GrTextureDomain::MakeTexelDomain(fgSubset, GrTextureDomain::kDecal_Mode),
                 GrTextureDomain::kDecal_Mode, GrSamplerState::Filter::kNearest);
         foregroundFP = GrColorSpaceXformEffect::Make(std::move(foregroundFP),
diff --git a/src/gpu/GrAHardwareBufferImageGenerator.cpp b/src/gpu/GrAHardwareBufferImageGenerator.cpp
index dd97f03..34b9c07 100644
--- a/src/gpu/GrAHardwareBufferImageGenerator.cpp
+++ b/src/gpu/GrAHardwareBufferImageGenerator.cpp
@@ -214,8 +214,9 @@
 
     GrMipMapped mipMapped = willNeedMipMaps ? GrMipMapped::kYes : GrMipMapped::kNo;
 
-    return GrSurfaceProxy::Copy(context, texProxy.get(), mipMapped, subset, SkBackingFit::kExact,
-                                SkBudgeted::kYes);
+    GrColorType grColorType = SkColorTypeToGrColorType(this->getInfo().colorType());
+    return GrSurfaceProxy::Copy(context, texProxy.get(), grColorType, mipMapped, subset,
+                                SkBackingFit::kExact, SkBudgeted::kYes);
 }
 
 bool GrAHardwareBufferImageGenerator::onIsValid(GrContext* context) const {
diff --git a/src/gpu/GrBackendTextureImageGenerator.cpp b/src/gpu/GrBackendTextureImageGenerator.cpp
index 5f54140..d63b952 100644
--- a/src/gpu/GrBackendTextureImageGenerator.cpp
+++ b/src/gpu/GrBackendTextureImageGenerator.cpp
@@ -218,7 +218,7 @@
         GrMipMapped mipMapped = willNeedMipMaps ? GrMipMapped::kYes : GrMipMapped::kNo;
         SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, info.width(), info.height());
 
-        return GrSurfaceProxy::Copy(context, proxy.get(), mipMapped, subset, SkBackingFit::kExact,
-                                    SkBudgeted::kYes);
+        return GrSurfaceProxy::Copy(context, proxy.get(), grColorType, mipMapped, subset,
+                                    SkBackingFit::kExact, SkBudgeted::kYes);
     }
 }
diff --git a/src/gpu/GrBitmapTextureMaker.cpp b/src/gpu/GrBitmapTextureMaker.cpp
index 5fbfcf1..4ec2b53 100644
--- a/src/gpu/GrBitmapTextureMaker.cpp
+++ b/src/gpu/GrBitmapTextureMaker.cpp
@@ -71,7 +71,9 @@
         // We need a mipped proxy, but we either found a proxy earlier that wasn't mipped or
         // generated a non mipped proxy. Thus we generate a new mipped surface and copy the original
         // proxy into the base layer. We will then let the gpu generate the rest of the mips.
-        if (auto mippedProxy = GrCopyBaseMipMapToTextureProxy(this->context(), proxy.get())) {
+        GrColorType srcColorType = SkColorTypeToGrColorType(fBitmap.colorType());
+        if (auto mippedProxy = GrCopyBaseMipMapToTextureProxy(this->context(), proxy.get(),
+                                                              srcColorType)) {
             SkASSERT(mippedProxy->origin() == kTopLeft_GrSurfaceOrigin);
             if (fOriginalKey.isValid()) {
                 // In this case we are stealing the key from the original proxy which should only
diff --git a/src/gpu/GrBlurUtils.cpp b/src/gpu/GrBlurUtils.cpp
index 71a54bd..7c922cb 100644
--- a/src/gpu/GrBlurUtils.cpp
+++ b/src/gpu/GrBlurUtils.cpp
@@ -38,7 +38,8 @@
                       const SkMatrix& viewMatrix,
                       const SkIRect& maskRect,
                       GrPaint&& paint,
-                      sk_sp<GrTextureProxy> mask) {
+                      sk_sp<GrTextureProxy> mask,
+                      GrColorType maskColorType) {
     SkMatrix inverse;
     if (!viewMatrix.invert(&inverse)) {
         return false;
@@ -47,7 +48,8 @@
     SkMatrix matrix = SkMatrix::MakeTrans(-SkIntToScalar(maskRect.fLeft),
                                           -SkIntToScalar(maskRect.fTop));
     matrix.preConcat(viewMatrix);
-    paint.addCoverageFragmentProcessor(GrSimpleTextureEffect::Make(std::move(mask), matrix));
+    paint.addCoverageFragmentProcessor(GrSimpleTextureEffect::Make(std::move(mask), maskColorType,
+                                                                   matrix));
 
     renderTargetContext->fillRectWithLocalMatrix(clip, std::move(paint), GrAA::kNo, SkMatrix::I(),
                                                  SkRect::Make(maskRect), inverse);
@@ -165,7 +167,7 @@
     }
 
     return draw_mask(renderTargetContext, clipData, viewMatrix, drawRect,
-                     std::move(paint), std::move(filteredMask));
+                     std::move(paint), std::move(filteredMask), GrColorType::kAlpha_8);
 }
 
 // Create a mask of 'shape' and return the resulting renderTargetContext
@@ -425,7 +427,8 @@
 
         if (filteredMask) {
             if (draw_mask(renderTargetContext, clip, viewMatrix,
-                          maskRect, std::move(paint), std::move(filteredMask))) {
+                          maskRect, std::move(paint), std::move(filteredMask),
+                          GrColorType::kAlpha_8)) {
                 // This path is completely drawn
                 return;
             }
diff --git a/src/gpu/GrFragmentProcessor.h b/src/gpu/GrFragmentProcessor.h
index 45d9a85..21e27b8 100644
--- a/src/gpu/GrFragmentProcessor.h
+++ b/src/gpu/GrFragmentProcessor.h
@@ -275,24 +275,24 @@
     /**
      * Can be used as a helper to decide which fragment processor OptimizationFlags should be set.
      * This assumes that the subclass output color will be a modulation of the input color with a
-     * value read from a texture of the passed config and that the texture contains premultiplied
-     * color or alpha values that are in range.
+     * value read from a texture of the passed color type and that the texture contains
+     * premultiplied color or alpha values that are in range.
      *
      * Since there are multiple ways in which a sampler may have its coordinates clamped or wrapped,
      * callers must determine on their own if the sampling uses a decal strategy in any way, in
-     * which case the texture may become transparent regardless of the pixel config.
+     * which case the texture may become transparent regardless of the color type.
      */
-    static OptimizationFlags ModulateForSamplerOptFlags(GrPixelConfig config, bool samplingDecal) {
+    static OptimizationFlags ModulateForSamplerOptFlags(GrColorType colorType, bool samplingDecal) {
         if (samplingDecal) {
             return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
         } else {
-            return ModulateForClampedSamplerOptFlags(config);
+            return ModulateForClampedSamplerOptFlags(colorType);
         }
     }
 
     // As above, but callers should somehow ensure or assert their sampler still uses clamping
-    static OptimizationFlags ModulateForClampedSamplerOptFlags(GrPixelConfig config) {
-        if (GrPixelConfigIsOpaque(config)) {
+    static OptimizationFlags ModulateForClampedSamplerOptFlags(GrColorType colorType) {
+        if (!GrColorTypeHasAlpha(colorType)) {
             return kCompatibleWithCoverageAsAlpha_OptimizationFlag |
                    kPreservesOpaqueInput_OptimizationFlag;
         } else {
diff --git a/src/gpu/GrPaint.cpp b/src/gpu/GrPaint.cpp
index 639d436..bc7f538 100644
--- a/src/gpu/GrPaint.cpp
+++ b/src/gpu/GrPaint.cpp
@@ -35,26 +35,16 @@
     this->setXPFactory(GrCoverageSetOpXPFactory::Get(regionOp, invertCoverage));
 }
 
-void GrPaint::addColorTextureProcessor(sk_sp<GrTextureProxy> proxy, const SkMatrix& matrix) {
-    this->addColorFragmentProcessor(GrSimpleTextureEffect::Make(std::move(proxy), matrix));
+void GrPaint::addColorTextureProcessor(sk_sp<GrTextureProxy> proxy, GrColorType srcColorType,
+                                       const SkMatrix& matrix) {
+    this->addColorFragmentProcessor(GrSimpleTextureEffect::Make(std::move(proxy), srcColorType,
+                                                                matrix));
 }
 
-void GrPaint::addColorTextureProcessor(sk_sp<GrTextureProxy> proxy, const SkMatrix& matrix,
-                                       const GrSamplerState& samplerState) {
-    this->addColorFragmentProcessor(GrSimpleTextureEffect::Make(std::move(proxy), matrix,
-                                                                samplerState));
-}
-
-void GrPaint::addCoverageTextureProcessor(sk_sp<GrTextureProxy> proxy,
-                                          const SkMatrix& matrix) {
-    this->addCoverageFragmentProcessor(GrSimpleTextureEffect::Make(std::move(proxy), matrix));
-}
-
-void GrPaint::addCoverageTextureProcessor(sk_sp<GrTextureProxy> proxy,
-                                          const SkMatrix& matrix,
-                                          const GrSamplerState& params) {
-    this->addCoverageFragmentProcessor(GrSimpleTextureEffect::Make(std::move(proxy), matrix,
-                                                                   params));
+void GrPaint::addColorTextureProcessor(sk_sp<GrTextureProxy> proxy, GrColorType srcColorType,
+                                       const SkMatrix& matrix, const GrSamplerState& samplerState) {
+    this->addColorFragmentProcessor(GrSimpleTextureEffect::Make(std::move(proxy), srcColorType,
+                                                                matrix, samplerState));
 }
 
 bool GrPaint::isConstantBlendedColor(SkPMColor4f* constantColor) const {
diff --git a/src/gpu/GrPaint.h b/src/gpu/GrPaint.h
index 7aafcb6..c2520b0 100644
--- a/src/gpu/GrPaint.h
+++ b/src/gpu/GrPaint.h
@@ -81,11 +81,9 @@
      * Helpers for adding color or coverage effects that sample a texture. The matrix is applied
      * to the src space position to compute texture coordinates.
      */
-    void addColorTextureProcessor(sk_sp<GrTextureProxy>, const SkMatrix&);
-    void addColorTextureProcessor(sk_sp<GrTextureProxy>, const SkMatrix&, const GrSamplerState&);
-
-    void addCoverageTextureProcessor(sk_sp<GrTextureProxy>, const SkMatrix&);
-    void addCoverageTextureProcessor(sk_sp<GrTextureProxy>, const SkMatrix&, const GrSamplerState&);
+    void addColorTextureProcessor(sk_sp<GrTextureProxy>, GrColorType srcColorType, const SkMatrix&);
+    void addColorTextureProcessor(sk_sp<GrTextureProxy>, GrColorType srcColorType, const SkMatrix&,
+                                  const GrSamplerState&);
 
     int numColorFragmentProcessors() const { return fColorFragmentProcessors.count(); }
     int numCoverageFragmentProcessors() const { return fCoverageFragmentProcessors.count(); }
diff --git a/src/gpu/GrProcessorUnitTest.h b/src/gpu/GrProcessorUnitTest.h
index 0e9392a..6b0443e 100644
--- a/src/gpu/GrProcessorUnitTest.h
+++ b/src/gpu/GrProcessorUnitTest.h
@@ -51,13 +51,16 @@
     GrProcessorTestData(SkRandom* random,
                         GrContext* context,
                         const GrRenderTargetContext* renderTargetContext,
-                        sk_sp<GrTextureProxy> proxies[2])
+                        sk_sp<GrTextureProxy> proxies[2],
+                        GrColorType proxyColorTypes[2])
             : fRandom(random)
             , fRenderTargetContext(renderTargetContext)
             , fContext(context) {
         SkASSERT(proxies[0] && proxies[1]);
         fProxies[0] = proxies[0];
         fProxies[1] = proxies[1];
+        fProxyColorTypes[0] = proxyColorTypes[0];
+        fProxyColorTypes[1] = proxyColorTypes[1];
     }
     SkRandom* fRandom;
     const GrRenderTargetContext* fRenderTargetContext;
@@ -67,10 +70,12 @@
     GrProxyProvider* proxyProvider();
     const GrCaps* caps();
     sk_sp<GrTextureProxy> textureProxy(int index) { return fProxies[index]; }
+    GrColorType textureProxyColorType(int index) { return fProxyColorTypes[index]; }
 
 private:
     GrContext* fContext;
     sk_sp<GrTextureProxy> fProxies[2];
+    GrColorType fProxyColorTypes[2];
 };
 
 class GrProcessor;
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 8d1d059..4aa5fcb 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -603,6 +603,7 @@
 
 void GrRenderTargetContext::drawTexturedQuad(const GrClip& clip,
                                              sk_sp<GrTextureProxy> proxy,
+                                             GrColorType srcColorType,
                                              sk_sp<GrColorSpaceXform> textureXform,
                                              GrSamplerState::Filter filter,
                                              const SkPMColor4f& color,
@@ -639,9 +640,10 @@
         // Use the provided domain, although hypothetically we could detect that the cropped local
         // quad is sufficiently inside the domain and the constraint could be dropped.
         this->addDrawOp(finalClip,
-                        GrTextureOp::Make(fContext, std::move(proxy), std::move(textureXform),
-                                          filter, color, saturate, blendMode, aaType, edgeFlags,
-                                          croppedDeviceQuad, croppedLocalQuad, domain));
+                        GrTextureOp::Make(fContext, std::move(proxy), srcColorType,
+                                          std::move(textureXform), filter, color, saturate,
+                                          blendMode, aaType, edgeFlags, croppedDeviceQuad,
+                                          croppedLocalQuad, domain));
     }
 }
 
@@ -888,7 +890,7 @@
 
             const SkRect* domain = constraint == SkCanvas::kStrict_SrcRectConstraint
                     ? &set[i].fSrcRect : nullptr;
-            this->drawTexturedQuad(clip, set[i].fProxy, texXform, filter,
+            this->drawTexturedQuad(clip, set[i].fProxy, set[i].fSrcColorType, texXform, filter,
                                    {alpha, alpha, alpha, alpha}, mode, aa, set[i].fAAFlags,
                                    quad, srcQuad, domain);
         }
@@ -1482,6 +1484,7 @@
                                              GrPaint&& paint,
                                              const SkMatrix& viewMatrix,
                                              sk_sp<GrTextureProxy> image,
+                                             GrColorType srcColorType,
                                              sk_sp<GrColorSpaceXform> csxf,
                                              GrSamplerState::Filter filter,
                                              std::unique_ptr<SkLatticeIter> iter,
@@ -1495,7 +1498,7 @@
 
     std::unique_ptr<GrDrawOp> op =
             GrLatticeOp::MakeNonAA(fContext, std::move(paint), viewMatrix, std::move(image),
-                                   std::move(csxf), filter, std::move(iter), dst);
+                                   srcColorType, std::move(csxf), filter, std::move(iter), dst);
     this->addDrawOp(clip, std::move(op));
 }
 
@@ -1580,6 +1583,7 @@
             // If the src is not texturable first try to make a copy to a texture.
             if (!texProxy) {
                 texProxy = GrSurfaceProxy::Copy(fContext, fRenderTargetProxy.get(),
+                                                this->colorInfo().colorType(),
                                                 GrMipMapped::kNo, srcRect, SkBackingFit::kApprox,
                                                 SkBudgeted::kNo);
                 if (!texProxy) {
@@ -1596,8 +1600,9 @@
                 callback(context, nullptr);
                 return;
             }
-            tempRTC->drawTexture(GrNoClip(), std::move(texProxy), GrSamplerState::Filter::kNearest,
-                                 SkBlendMode::kSrc, SK_PMColor4fWHITE, srcRectToDraw,
+            tempRTC->drawTexture(GrNoClip(), std::move(texProxy), this->colorInfo().colorType(),
+                                 GrSamplerState::Filter::kNearest, SkBlendMode::kSrc,
+                                 SK_PMColor4fWHITE, srcRectToDraw,
                                  SkRect::MakeWH(srcRect.width(), srcRect.height()), GrAA::kNo,
                                  GrQuadAAFlags::kNone, SkCanvas::kFast_SrcRectConstraint,
                                  SkMatrix::I(), std::move(xform));
@@ -1797,8 +1802,9 @@
                 callback(context, nullptr);
                 return;
             }
-            tempRTC->drawTexture(GrNoClip(), std::move(texProxy), GrSamplerState::Filter::kNearest,
-                                 SkBlendMode::kSrc, SK_PMColor4fWHITE, srcRectToDraw,
+            tempRTC->drawTexture(GrNoClip(), std::move(texProxy), this->colorInfo().colorType(),
+                                 GrSamplerState::Filter::kNearest, SkBlendMode::kSrc,
+                                 SK_PMColor4fWHITE, srcRectToDraw,
                                  SkRect::MakeWH(srcRect.width(), srcRect.height()), GrAA::kNo,
                                  GrQuadAAFlags::kNone, SkCanvas::kFast_SrcRectConstraint,
                                  SkMatrix::I(), std::move(xform));
@@ -1811,6 +1817,9 @@
         callback(context, nullptr);
         return;
     }
+    GrColorType srcColorType = tempRTC ? tempRTC->colorInfo().colorType()
+                                       : this->colorInfo().colorType();
+
     auto yRTC = direct->priv().makeDeferredRenderTargetContextWithFallback(
             SkBackingFit::kApprox, dstSize.width(), dstSize.height(), GrColorType::kAlpha_8,
             dstColorSpace, 1, GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin);
@@ -1874,7 +1883,7 @@
     std::fill_n(yM, 15, 0.f);
     yM[15] = baseM[0]; yM[16] = baseM[1]; yM[17] = baseM[2]; yM[18] = 0; yM[19] = baseM[3];
     GrPaint yPaint;
-    yPaint.addColorTextureProcessor(srcProxy, texMatrix);
+    yPaint.addColorTextureProcessor(srcProxy, srcColorType, texMatrix);
     auto yFP = GrColorMatrixFragmentProcessor::Make(yM, false, true, false);
     yPaint.addColorFragmentProcessor(std::move(yFP));
     yPaint.setPorterDuffXPFactory(SkBlendMode::kSrc);
@@ -1893,7 +1902,8 @@
     std::fill_n(uM, 15, 0.f);
     uM[15] = baseM[4]; uM[16] = baseM[5]; uM[17] = baseM[6]; uM[18] = 0; uM[19] = baseM[7];
     GrPaint uPaint;
-    uPaint.addColorTextureProcessor(srcProxy, texMatrix, GrSamplerState::ClampBilerp());
+    uPaint.addColorTextureProcessor(srcProxy, srcColorType, texMatrix,
+                                    GrSamplerState::ClampBilerp());
     auto uFP = GrColorMatrixFragmentProcessor::Make(uM, false, true, false);
     uPaint.addColorFragmentProcessor(std::move(uFP));
     uPaint.setPorterDuffXPFactory(SkBlendMode::kSrc);
@@ -1911,7 +1921,8 @@
     std::fill_n(vM, 15, 0.f);
     vM[15] = baseM[8]; vM[16] = baseM[9]; vM[17] = baseM[10]; vM[18] = 0; vM[19] = baseM[11];
     GrPaint vPaint;
-    vPaint.addColorTextureProcessor(srcProxy, texMatrix, GrSamplerState::ClampBilerp());
+    vPaint.addColorTextureProcessor(srcProxy, srcColorType, texMatrix,
+                                    GrSamplerState::ClampBilerp());
     auto vFP = GrColorMatrixFragmentProcessor::Make(vM, false, true, false);
     vPaint.addColorFragmentProcessor(std::move(vFP));
     vPaint.setPorterDuffXPFactory(SkBlendMode::kSrc);
@@ -2416,8 +2427,8 @@
         fit = SkBackingFit::kApprox;
     }
     sk_sp<GrTextureProxy> newProxy = GrSurfaceProxy::Copy(
-            fContext, fRenderTargetProxy.get(), GrMipMapped::kNo, copyRect, fit, SkBudgeted::kYes,
-            restrictions.fRectsMustMatch);
+            fContext, fRenderTargetProxy.get(), this->colorInfo().colorType(), GrMipMapped::kNo,
+            copyRect, fit, SkBudgeted::kYes, restrictions.fRectsMustMatch);
     SkASSERT(newProxy);
 
     dstProxy->setProxy(std::move(newProxy));
@@ -2425,8 +2436,8 @@
     return true;
 }
 
-bool GrRenderTargetContext::blitTexture(GrTextureProxy* src, const SkIRect& srcRect,
-                                        const SkIPoint& dstPoint) {
+bool GrRenderTargetContext::blitTexture(GrTextureProxy* src, GrColorType srcColorType,
+                                        const SkIRect& srcRect, const SkIPoint& dstPoint) {
     SkIRect clippedSrcRect;
     SkIPoint clippedDstPoint;
     if (!GrClipSrcRectAndDstPoint(this->asSurfaceProxy()->isize(), src->isize(), srcRect, dstPoint,
@@ -2436,8 +2447,7 @@
 
     GrPaint paint;
     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-    auto fp = GrSimpleTextureEffect::Make(sk_ref_sp(src->asTextureProxy()),
-                                          SkMatrix::I());
+    auto fp = GrSimpleTextureEffect::Make(sk_ref_sp(src), srcColorType, SkMatrix::I());
     if (!fp) {
         return false;
     }
diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h
index 74dee28..c10bf00 100644
--- a/src/gpu/GrRenderTargetContext.h
+++ b/src/gpu/GrRenderTargetContext.h
@@ -194,14 +194,14 @@
      * specifies the rectangle to draw in local coords which will be transformed by 'viewMatrix' to
      * device space.
      */
-    void drawTexture(const GrClip& clip, sk_sp<GrTextureProxy> proxy, GrSamplerState::Filter filter,
-                     SkBlendMode mode, const SkPMColor4f& color, const SkRect& srcRect,
-                     const SkRect& dstRect, GrAA aa, GrQuadAAFlags edgeAA,
+    void drawTexture(const GrClip& clip, sk_sp<GrTextureProxy> proxy, GrColorType srcColorType,
+                     GrSamplerState::Filter filter, SkBlendMode mode, const SkPMColor4f& color,
+                     const SkRect& srcRect, const SkRect& dstRect, GrAA aa, GrQuadAAFlags edgeAA,
                      SkCanvas::SrcRectConstraint constraint, const SkMatrix& viewMatrix,
                      sk_sp<GrColorSpaceXform> texXform) {
         const SkRect* domain = constraint == SkCanvas::kStrict_SrcRectConstraint ?
                 &srcRect : nullptr;
-        this->drawTexturedQuad(clip, std::move(proxy), std::move(texXform), filter,
+        this->drawTexturedQuad(clip, std::move(proxy), srcColorType, std::move(texXform), filter,
                                color, mode, aa, edgeAA, GrQuad::MakeFromRect(dstRect, viewMatrix),
                                GrQuad(srcRect), domain);
     }
@@ -212,19 +212,20 @@
      * 'domain' is null, it's equivalent to using the fast src rect constraint. If 'domain' is
      * provided, the strict src rect constraint is applied using 'domain'.
      */
-    void drawTextureQuad(const GrClip& clip, sk_sp<GrTextureProxy> proxy,
+    void drawTextureQuad(const GrClip& clip, sk_sp<GrTextureProxy> proxy, GrColorType srcColorType,
                          GrSamplerState::Filter filter, SkBlendMode mode, const SkPMColor4f& color,
                          const SkPoint srcQuad[4], const SkPoint dstQuad[4], GrAA aa,
                          GrQuadAAFlags edgeAA, const SkRect* domain, const SkMatrix& viewMatrix,
                          sk_sp<GrColorSpaceXform> texXform) {
-        this->drawTexturedQuad(clip, std::move(proxy), std::move(texXform), filter, color, mode,
-                               aa, edgeAA, GrQuad::MakeFromSkQuad(dstQuad, viewMatrix),
+        this->drawTexturedQuad(clip, std::move(proxy), srcColorType, std::move(texXform), filter,
+                               color, mode, aa, edgeAA, GrQuad::MakeFromSkQuad(dstQuad, viewMatrix),
                                GrQuad::MakeFromSkQuad(srcQuad, SkMatrix::I()), domain);
     }
 
     /** Used with drawTextureSet */
     struct TextureSetEntry {
         sk_sp<GrTextureProxy> fProxy;
+        GrColorType fSrcColorType;
         SkRect fSrcRect;
         SkRect fDstRect;
         const SkPoint* fDstClipQuad; // Must be null, or point to an array of 4 points
@@ -422,6 +423,7 @@
                           GrPaint&&,
                           const SkMatrix& viewMatrix,
                           sk_sp<GrTextureProxy>,
+                          GrColorType srcColorType,
                           sk_sp<GrColorSpaceXform>,
                           GrSamplerState::Filter,
                           std::unique_ptr<SkLatticeIter>,
@@ -432,7 +434,8 @@
      * of the srcRect. The srcRect and dstRect are clipped to the bounds of the src and dst surfaces
      * respectively.
      */
-    bool blitTexture(GrTextureProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint);
+    bool blitTexture(GrTextureProxy* src, GrColorType srcColorType, const SkIRect& srcRect,
+                     const SkIPoint& dstPoint);
 
     /**
      * Adds the necessary signal and wait semaphores and adds the passed in SkDrawable to the
@@ -545,7 +548,8 @@
     friend void test_draw_op(GrContext*,
                              GrRenderTargetContext*,
                              std::unique_ptr<GrFragmentProcessor>,
-                             sk_sp<GrTextureProxy>);
+                             sk_sp<GrTextureProxy>,
+                             GrColorType);
 
     GrOpsTask::CanDiscardPreviousOps canDiscardPreviousOpsOnFullClear() const;
     void setNeedsStencil(bool useMixedSamplesIfNotMSAA);
@@ -593,6 +597,7 @@
     // Like drawFilledQuad but does not require using a GrPaint or FP for texturing
     void drawTexturedQuad(const GrClip& clip,
                           sk_sp<GrTextureProxy> proxy,
+                          GrColorType srcColorType,
                           sk_sp<GrColorSpaceXform> textureXform,
                           GrSamplerState::Filter filter,
                           const SkPMColor4f& color,
diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp
index 963dece..4245e9e 100644
--- a/src/gpu/GrSoftwarePathRenderer.cpp
+++ b/src/gpu/GrSoftwarePathRenderer.cpp
@@ -144,6 +144,7 @@
 
 void GrSoftwarePathRenderer::DrawToTargetWithShapeMask(
         sk_sp<GrTextureProxy> proxy,
+        GrColorType srcColorType,
         GrRenderTargetContext* renderTargetContext,
         GrPaint&& paint,
         const GrUserStencilSettings& userStencilSettings,
@@ -165,7 +166,7 @@
                                               SkIntToScalar(-textureOriginInDeviceSpace.fY));
     maskMatrix.preConcat(viewMatrix);
     paint.addCoverageFragmentProcessor(GrSimpleTextureEffect::Make(
-            std::move(proxy), maskMatrix, GrSamplerState::Filter::kNearest));
+            std::move(proxy), srcColorType, maskMatrix, GrSamplerState::Filter::kNearest));
     DrawNonAARect(renderTargetContext, std::move(paint), userStencilSettings, clip, SkMatrix::I(),
                   dstRect, invert);
 }
@@ -386,8 +387,8 @@
                           unclippedDevShapeBounds);
     }
     DrawToTargetWithShapeMask(
-            std::move(proxy), args.fRenderTargetContext, std::move(args.fPaint),
-            *args.fUserStencilSettings, *args.fClip, *args.fViewMatrix,
+            std::move(proxy), GrColorType::kAlpha_8, args.fRenderTargetContext,
+            std::move(args.fPaint), *args.fUserStencilSettings, *args.fClip, *args.fViewMatrix,
             SkIPoint{boundsForMask->fLeft, boundsForMask->fTop}, *boundsForMask);
 
     return true;
diff --git a/src/gpu/GrSoftwarePathRenderer.h b/src/gpu/GrSoftwarePathRenderer.h
index a510c7b..d407791 100644
--- a/src/gpu/GrSoftwarePathRenderer.h
+++ b/src/gpu/GrSoftwarePathRenderer.h
@@ -52,6 +52,7 @@
     // space. The 'viewMatrix' will be used to ensure the correct local coords are provided to
     // any fragment processors in the paint.
     static void DrawToTargetWithShapeMask(sk_sp<GrTextureProxy> proxy,
+                                          GrColorType srcColorType,
                                           GrRenderTargetContext* renderTargetContext,
                                           GrPaint&& paint,
                                           const GrUserStencilSettings& userStencilSettings,
diff --git a/src/gpu/GrSurfaceContext.cpp b/src/gpu/GrSurfaceContext.cpp
index eb198cb..4b5e0a8 100644
--- a/src/gpu/GrSurfaceContext.cpp
+++ b/src/gpu/GrSurfaceContext.cpp
@@ -146,7 +146,7 @@
         if (canvas2DFastPath) {
             fp = direct->priv().createPMToUPMEffect(
                     GrSimpleTextureEffect::Make(sk_ref_sp(srcProxy->asTextureProxy()),
-                                                SkMatrix::I()));
+                                                this->colorInfo().colorType(), SkMatrix::I()));
             if (dstInfo.colorType() == GrColorType::kBGRA_8888) {
                 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), GrSwizzle::BGRA());
                 dstInfo = dstInfo.makeColorType(GrColorType::kRGBA_8888);
@@ -156,7 +156,8 @@
             // double unpremul.
             dstInfo = dstInfo.makeAlphaType(kPremul_SkAlphaType);
         } else {
-            fp = GrSimpleTextureEffect::Make(sk_ref_sp(srcProxy->asTextureProxy()), SkMatrix::I());
+            fp = GrSimpleTextureEffect::Make(sk_ref_sp(srcProxy->asTextureProxy()),
+                                             this->colorInfo().colorType(), SkMatrix::I());
         }
         if (!fp) {
             return false;
@@ -340,13 +341,14 @@
             std::unique_ptr<GrFragmentProcessor> fp;
             if (canvas2DFastPath) {
                 fp = direct->priv().createUPMToPMEffect(
-                        GrSimpleTextureEffect::Make(std::move(tempProxy), SkMatrix::I()));
+                        GrSimpleTextureEffect::Make(std::move(tempProxy), colorType,
+                                                    SkMatrix::I()));
                 // Important: check the original src color type here!
                 if (origSrcInfo.colorType() == GrColorType::kBGRA_8888) {
                     fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), GrSwizzle::BGRA());
                 }
             } else {
-                fp = GrSimpleTextureEffect::Make(std::move(tempProxy), SkMatrix::I());
+                fp = GrSimpleTextureEffect::Make(std::move(tempProxy), colorType, SkMatrix::I());
             }
             if (!fp) {
                 return false;
@@ -452,9 +454,11 @@
     int srcY = srcRect.fTop;
     sk_sp<GrTextureProxy> texProxy = sk_ref_sp(this->asTextureProxy());
     SkCanvas::SrcRectConstraint constraint = SkCanvas::kStrict_SrcRectConstraint;
+    GrColorType srcColorType = this->colorInfo().colorType();
     if (!texProxy) {
-        texProxy = GrSurfaceProxy::Copy(fContext, this->asSurfaceProxy(), GrMipMapped::kNo, srcRect,
-                                        SkBackingFit::kApprox, SkBudgeted::kNo);
+        texProxy = GrSurfaceProxy::Copy(fContext, this->asSurfaceProxy(), srcColorType,
+                                        GrMipMapped::kNo, srcRect, SkBackingFit::kApprox,
+                                        SkBudgeted::kNo);
         if (!texProxy) {
             return nullptr;
         }
@@ -477,6 +481,7 @@
         stepsY = sy != 1.f;
     }
     SkASSERT(stepsX || stepsY);
+
     // Within a rescaling pass A is the input (if not null) and B is the output. At the end of the
     // pass B is moved to A. If 'this' is the input on the first pass then tempA is null.
     std::unique_ptr<GrRenderTargetContext> tempA;
@@ -497,7 +502,7 @@
         if (!linearRTC) {
             return nullptr;
         }
-        linearRTC->drawTexture(GrNoClip(), texProxy, GrSamplerState::Filter::kNearest,
+        linearRTC->drawTexture(GrNoClip(), texProxy, srcColorType, GrSamplerState::Filter::kNearest,
                                SkBlendMode::kSrc, SK_PMColor4fWHITE, SkRect::Make(srcRect),
                                SkRect::MakeWH(srcW, srcH), GrAA::kNo, GrQuadAAFlags::kNone,
                                constraint, SkMatrix::I(), std::move(xform));
@@ -561,9 +566,10 @@
             if (srcW != texProxy->width() || srcH != texProxy->height()) {
                 auto domain = GrTextureDomain::MakeTexelDomain(
                         SkIRect::MakeXYWH(srcX, srcY, srcW, srcH), GrTextureDomain::kClamp_Mode);
-                fp = GrBicubicEffect::Make(texProxy, matrix, domain, dir, prevAlphaType);
+                fp = GrBicubicEffect::Make(texProxy, srcColorType, matrix, domain, dir,
+                                           prevAlphaType);
             } else {
-                fp = GrBicubicEffect::Make(texProxy, matrix, dir, prevAlphaType);
+                fp = GrBicubicEffect::Make(texProxy, srcColorType, matrix, dir, prevAlphaType);
             }
             if (xform) {
                 fp = GrColorSpaceXformEffect::Make(std::move(fp), std::move(xform));
@@ -577,9 +583,9 @@
             auto filter = rescaleQuality == kNone_SkFilterQuality ? GrSamplerState::Filter::kNearest
                                                                   : GrSamplerState::Filter::kBilerp;
             auto srcSubset = SkRect::MakeXYWH(srcX, srcY, srcW, srcH);
-            tempB->drawTexture(GrNoClip(), texProxy, filter, SkBlendMode::kSrc, SK_PMColor4fWHITE,
-                                 srcSubset, dstRect, GrAA::kNo, GrQuadAAFlags::kNone, constraint,
-                                 SkMatrix::I(), std::move(xform));
+            tempB->drawTexture(GrNoClip(), texProxy, srcColorType, filter, SkBlendMode::kSrc,
+                               SK_PMColor4fWHITE, srcSubset, dstRect, GrAA::kNo,
+                               GrQuadAAFlags::kNone, constraint, SkMatrix::I(), std::move(xform));
         }
         texProxy = tempB->asTextureProxyRef();
         tempA = std::move(tempB);
diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp
index 2abefc8..a487847 100644
--- a/src/gpu/GrSurfaceProxy.cpp
+++ b/src/gpu/GrSurfaceProxy.cpp
@@ -333,6 +333,7 @@
 
 sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrRecordingContext* context,
                                            GrSurfaceProxy* src,
+                                           GrColorType srcColorType,
                                            GrMipMapped mipMapped,
                                            SkIRect srcRect,
                                            SkBackingFit fit,
@@ -374,7 +375,8 @@
                 fit, width, height, colorType, nullptr, 1, mipMapped, src->origin(), nullptr,
                 budgeted);
 
-        if (dstContext && dstContext->blitTexture(src->asTextureProxy(), srcRect, dstPoint)) {
+        if (dstContext && dstContext->blitTexture(src->asTextureProxy(), srcColorType, srcRect,
+                                                  dstPoint)) {
             return dstContext->asTextureProxyRef();
         }
     }
@@ -383,11 +385,11 @@
 }
 
 sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrRecordingContext* context, GrSurfaceProxy* src,
-                                           GrMipMapped mipMapped, SkBackingFit fit,
-                                           SkBudgeted budgeted) {
+                                           GrColorType srcColorType, GrMipMapped mipMapped,
+                                           SkBackingFit fit, SkBudgeted budgeted) {
     SkASSERT(!src->isFullyLazy());
-    return Copy(context, src, mipMapped, SkIRect::MakeWH(src->width(), src->height()), fit,
-                budgeted);
+    return Copy(context, src, srcColorType, mipMapped, SkIRect::MakeWH(src->width(), src->height()),
+                fit, budgeted);
 }
 
 #if GR_TEST_UTILS
diff --git a/src/gpu/GrSurfaceProxy.h b/src/gpu/GrSurfaceProxy.h
index 2b7395b..7ce65d8 100644
--- a/src/gpu/GrSurfaceProxy.h
+++ b/src/gpu/GrSurfaceProxy.h
@@ -292,13 +292,15 @@
 
     // Helper function that creates a temporary SurfaceContext to perform the copy
     // The copy is is not a render target and not multisampled.
-    static sk_sp<GrTextureProxy> Copy(GrRecordingContext*, GrSurfaceProxy* src, GrMipMapped,
+    static sk_sp<GrTextureProxy> Copy(GrRecordingContext*, GrSurfaceProxy* src,
+                                      GrColorType srcColorType, GrMipMapped,
                                       SkIRect srcRect, SkBackingFit, SkBudgeted,
                                       RectsMustMatch = RectsMustMatch::kNo);
 
     // Copy the entire 'src'
-    static sk_sp<GrTextureProxy> Copy(GrRecordingContext*, GrSurfaceProxy* src, GrMipMapped,
-                                      SkBackingFit, SkBudgeted);
+    static sk_sp<GrTextureProxy> Copy(GrRecordingContext*, GrSurfaceProxy* src,
+                                      GrColorType srcColortype, GrMipMapped, SkBackingFit,
+                                      SkBudgeted);
 
 #if GR_TEST_UTILS
     int32_t testingOnly_getBackingRefCnt() const;
diff --git a/src/gpu/GrTextureProducer.cpp b/src/gpu/GrTextureProducer.cpp
index 73f7113..7b54e9c 100644
--- a/src/gpu/GrTextureProducer.cpp
+++ b/src/gpu/GrTextureProducer.cpp
@@ -42,7 +42,8 @@
 
     if (copyParams.fFilter == GrSamplerState::Filter::kNearest && !needsDomain && !resizing &&
         dstWillRequireMipMaps) {
-        sk_sp<GrTextureProxy> proxy = GrCopyBaseMipMapToTextureProxy(context, inputProxy.get());
+        sk_sp<GrTextureProxy> proxy = GrCopyBaseMipMapToTextureProxy(context, inputProxy.get(),
+                                                                     colorType);
         if (proxy) {
             return proxy;
         }
@@ -63,11 +64,12 @@
         // better!
         SkASSERT(copyParams.fFilter != GrSamplerState::Filter::kMipMap);
         paint.addColorFragmentProcessor(
-            GrTextureDomainEffect::Make(std::move(inputProxy), SkMatrix::I(), domain,
+            GrTextureDomainEffect::Make(std::move(inputProxy), colorType, SkMatrix::I(), domain,
                                         GrTextureDomain::kClamp_Mode, copyParams.fFilter));
     } else {
         GrSamplerState samplerState(GrSamplerState::WrapMode::kClamp, copyParams.fFilter);
-        paint.addColorTextureProcessor(std::move(inputProxy), SkMatrix::I(), samplerState);
+        paint.addColorTextureProcessor(std::move(inputProxy), colorType, SkMatrix::I(),
+                                       samplerState);
     }
     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
@@ -199,18 +201,20 @@
         const GrSamplerState::Filter* filterOrNullForBicubic) {
     SkASSERT(kTightCopy_DomainMode != domainMode);
     bool clampToBorderSupport = fContext->priv().caps()->clampToBorderSupport();
+    GrColorType srcColorType = this->colorType();
     if (filterOrNullForBicubic) {
         if (kDomain_DomainMode == domainMode || (fDomainNeedsDecal && !clampToBorderSupport)) {
             GrTextureDomain::Mode wrapMode = fDomainNeedsDecal ? GrTextureDomain::kDecal_Mode
                                                                : GrTextureDomain::kClamp_Mode;
-            return GrTextureDomainEffect::Make(std::move(proxy), textureMatrix, domain,
-                                               wrapMode, *filterOrNullForBicubic);
+            return GrTextureDomainEffect::Make(std::move(proxy), srcColorType, textureMatrix,
+                                               domain, wrapMode, *filterOrNullForBicubic);
         } else {
             GrSamplerState::WrapMode wrapMode =
                     fDomainNeedsDecal ? GrSamplerState::WrapMode::kClampToBorder
                                       : GrSamplerState::WrapMode::kClamp;
             GrSamplerState samplerState(wrapMode, *filterOrNullForBicubic);
-            return GrSimpleTextureEffect::Make(std::move(proxy), textureMatrix, samplerState);
+            return GrSimpleTextureEffect::Make(std::move(proxy), srcColorType, textureMatrix,
+                                               samplerState);
         }
     } else {
         static const GrSamplerState::WrapMode kClampClamp[] = {
@@ -222,11 +226,11 @@
         if (kDomain_DomainMode == domainMode || (fDomainNeedsDecal && !clampToBorderSupport)) {
             GrTextureDomain::Mode wrapMode = fDomainNeedsDecal ? GrTextureDomain::kDecal_Mode
                                          : GrTextureDomain::kClamp_Mode;
-            return GrBicubicEffect::Make(std::move(proxy), textureMatrix, kClampClamp, wrapMode,
-                                         wrapMode, kDir, this->alphaType(),
+            return GrBicubicEffect::Make(std::move(proxy), srcColorType, textureMatrix, kClampClamp,
+                                         wrapMode, wrapMode, kDir, this->alphaType(),
                                          kDomain_DomainMode == domainMode ? &domain : nullptr);
         } else {
-            return GrBicubicEffect::Make(std::move(proxy), textureMatrix,
+            return GrBicubicEffect::Make(std::move(proxy), srcColorType, textureMatrix,
                                          fDomainNeedsDecal ? kDecalDecal : kClampClamp, kDir,
                                          this->alphaType());
         }
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index d9aa582..77b9963 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -230,6 +230,7 @@
 
         SkASSERT(fRenderTargetContext->asTextureProxy());
         SkAssertResult(rtc->blitTexture(fRenderTargetContext->asTextureProxy(),
+                                        fRenderTargetContext->colorInfo().colorType(),
                                         SkIRect::MakeWH(this->width(), this->height()),
                                         SkIPoint::Make(0,0)));
     }
@@ -930,6 +931,8 @@
     SkMatrix texMatrix = SkMatrix::MakeRectToRect(dstRect, srcRect, SkMatrix::kFill_ScaleToFit);
     texMatrix.postScale(scales[0], scales[1]);
 
+    GrColorType srcColorType = SkColorTypeToGrColorType(bitmap.colorType());
+
     // Construct a GrPaint by setting the bitmap texture as the first effect and then configuring
     // the rest from the SkPaint.
     std::unique_ptr<GrFragmentProcessor> fp;
@@ -951,19 +954,20 @@
         }
         if (bicubic) {
             static constexpr auto kDir = GrBicubicEffect::Direction::kXY;
-            fp = GrBicubicEffect::Make(std::move(proxy), texMatrix, domain, kDir,
+            fp = GrBicubicEffect::Make(std::move(proxy), srcColorType, texMatrix, domain, kDir,
                                        bitmap.alphaType());
         } else {
-            fp = GrTextureDomainEffect::Make(std::move(proxy), texMatrix, domain,
+            fp = GrTextureDomainEffect::Make(std::move(proxy), srcColorType, texMatrix, domain,
                                              GrTextureDomain::kClamp_Mode, samplerState.filter());
         }
     } else if (bicubic) {
         SkASSERT(GrSamplerState::Filter::kNearest == samplerState.filter());
         GrSamplerState::WrapMode wrapMode[2] = {samplerState.wrapModeX(), samplerState.wrapModeY()};
         static constexpr auto kDir = GrBicubicEffect::Direction::kXY;
-        fp = GrBicubicEffect::Make(std::move(proxy), texMatrix, wrapMode, kDir, bitmap.alphaType());
+        fp = GrBicubicEffect::Make(std::move(proxy), srcColorType, texMatrix, wrapMode, kDir,
+                                   bitmap.alphaType());
     } else {
-        fp = GrSimpleTextureEffect::Make(std::move(proxy), texMatrix, samplerState);
+        fp = GrSimpleTextureEffect::Make(std::move(proxy), srcColorType, texMatrix, samplerState);
     }
 
     fp = GrColorSpaceXformEffect::Make(std::move(fp), bitmap.colorSpace(), bitmap.alphaType(),
@@ -1034,7 +1038,8 @@
 
     tmpUnfiltered.setImageFilter(nullptr);
 
-    auto fp = GrSimpleTextureEffect::Make(std::move(proxy), SkMatrix::I());
+    GrColorType srcColorType = SkColorTypeToGrColorType(result->colorType());
+    auto fp = GrSimpleTextureEffect::Make(std::move(proxy), srcColorType, SkMatrix::I());
     fp = GrColorSpaceXformEffect::Make(std::move(fp), result->getColorSpace(), result->alphaType(),
                                        fRenderTargetContext->colorInfo().colorSpace());
     if (GrColorTypeIsAlphaOnly(SkColorTypeToGrColorType(result->colorType()))) {
@@ -1071,8 +1076,10 @@
 
         std::unique_ptr<GrFragmentProcessor> cfp;
         if (clipProxy && ctm.invert(&inverseClipMatrix)) {
-            cfp = GrSimpleTextureEffect::Make(std::move(clipProxy), inverseClipMatrix, sampler);
-            if (clipImage->colorType() != kAlpha_8_SkColorType) {
+            GrColorType srcColorType = SkColorTypeToGrColorType(clipImage->colorType());
+            cfp = GrSimpleTextureEffect::Make(std::move(clipProxy), srcColorType, inverseClipMatrix,
+                                              sampler);
+            if (srcColorType != GrColorType::kAlpha_8) {
                 cfp = GrFragmentProcessor::SwizzleOutput(std::move(cfp), GrSwizzle::AAAA());
             }
         }
@@ -1247,6 +1254,7 @@
         // texture that matches the device contents
         proxy = GrSurfaceProxy::Copy(fContext.get(),
                                      rtc->asSurfaceProxy(),
+                                     rtc->colorInfo().colorType(),
                                      GrMipMapped::kNo,      // Don't auto generate mips
                                      subset,
                                      SkBackingFit::kApprox,
@@ -1362,8 +1370,8 @@
                                         dstColorSpace,          kPremul_SkAlphaType);
 
     fRenderTargetContext->drawImageLattice(this->clip(), std::move(grPaint), this->ctm(),
-                                           std::move(proxy), std::move(csxf), filter,
-                                           std::move(iter), dst);
+                                           std::move(proxy), producer->colorType(), std::move(csxf),
+                                           filter, std::move(iter), dst);
 }
 
 void SkGpuDevice::drawImageLattice(const SkImage* image,
diff --git a/src/gpu/SkGpuDevice_drawTexture.cpp b/src/gpu/SkGpuDevice_drawTexture.cpp
index 869f348..20c4976 100644
--- a/src/gpu/SkGpuDevice_drawTexture.cpp
+++ b/src/gpu/SkGpuDevice_drawTexture.cpp
@@ -220,13 +220,14 @@
         SkPoint srcQuad[4];
         GrMapRectPoints(dstRect, srcRect, dstClip, srcQuad, 4);
 
-        rtc->drawTextureQuad(clip, std::move(proxy), filter, paint.getBlendMode(), color,
-                             srcQuad, dstClip, aa, aaFlags,
+        rtc->drawTextureQuad(clip, std::move(proxy), srcColorInfo.colorType(), filter,
+                             paint.getBlendMode(), color, srcQuad, dstClip, aa, aaFlags,
                              constraint == SkCanvas::kStrict_SrcRectConstraint ? &srcRect : nullptr,
                              ctm, std::move(textureXform));
     } else {
-        rtc->drawTexture(clip, std::move(proxy), filter, paint.getBlendMode(), color, srcRect,
-                         dstRect, aa, aaFlags, constraint, ctm, std::move(textureXform));
+        rtc->drawTexture(clip, std::move(proxy), srcColorInfo.colorType(), filter,
+                         paint.getBlendMode(), color, srcRect, dstRect, aa, aaFlags, constraint,
+                         ctm, std::move(textureXform));
     }
 }
 
@@ -552,6 +553,7 @@
         }
 
         textures[i].fProxy = std::move(proxy);
+        textures[i].fSrcColorType = SkColorTypeToGrColorType(image->colorType());
         textures[i].fSrcRect = set[i].fSrcRect;
         textures[i].fDstRect = set[i].fDstRect;
         textures[i].fDstClipQuad = clip;
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 52adfac..bdb3c3c 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -125,14 +125,15 @@
 }
 
 sk_sp<GrTextureProxy> GrCopyBaseMipMapToTextureProxy(GrRecordingContext* ctx,
-                                                     GrTextureProxy* baseProxy) {
+                                                     GrTextureProxy* baseProxy,
+                                                     GrColorType srcColorType) {
     SkASSERT(baseProxy);
 
     if (!ctx->priv().caps()->isFormatCopyable(baseProxy->backendFormat())) {
         return nullptr;
     }
-    return GrSurfaceProxy::Copy(ctx, baseProxy, GrMipMapped::kYes, SkBackingFit::kExact,
-                                SkBudgeted::kYes);
+    return GrSurfaceProxy::Copy(ctx, baseProxy, srcColorType, GrMipMapped::kYes,
+                                SkBackingFit::kExact, SkBudgeted::kYes);
 }
 
 sk_sp<GrTextureProxy> GrRefCachedBitmapTextureProxy(GrRecordingContext* ctx,
diff --git a/src/gpu/SkGr.h b/src/gpu/SkGr.h
index 9550bc0..79a6882 100644
--- a/src/gpu/SkGr.h
+++ b/src/gpu/SkGr.h
@@ -194,7 +194,8 @@
  * Creates a new texture with mipmap levels and copies the baseProxy into the base layer.
  */
 sk_sp<GrTextureProxy> GrCopyBaseMipMapToTextureProxy(GrRecordingContext*,
-                                                     GrTextureProxy* baseProxy);
+                                                     GrTextureProxy* baseProxy,
+                                                     GrColorType srcColorType);
 
 /*
  * Create a texture proxy from the provided bitmap by wrapping it in an image and calling
diff --git a/src/gpu/effects/GrBicubicEffect.cpp b/src/gpu/effects/GrBicubicEffect.cpp
index e59ed01..6d7b431 100644
--- a/src/gpu/effects/GrBicubicEffect.cpp
+++ b/src/gpu/effects/GrBicubicEffect.cpp
@@ -162,13 +162,14 @@
                     processor.textureSampler(0).samplerState());
 }
 
-GrBicubicEffect::GrBicubicEffect(sk_sp<GrTextureProxy> proxy, const SkMatrix& matrix,
-                                 const SkRect& domain, const GrSamplerState::WrapMode wrapModes[2],
+GrBicubicEffect::GrBicubicEffect(sk_sp<GrTextureProxy> proxy, GrColorType srcColorType,
+                                 const SkMatrix& matrix, const SkRect& domain,
+                                 const GrSamplerState::WrapMode wrapModes[2],
                                  GrTextureDomain::Mode modeX, GrTextureDomain::Mode modeY,
                                  Direction direction, SkAlphaType alphaType)
         : INHERITED{kGrBicubicEffect_ClassID,
                     ModulateForSamplerOptFlags(
-                            proxy->config(),
+                            srcColorType,
                             GrTextureDomain::IsDecalSampled(wrapModes, modeX, modeY))}
         , fCoordTransform(matrix, proxy.get())
         , fDomain(proxy.get(), domain, modeX, modeY)
@@ -226,8 +227,8 @@
             direction = Direction::kXY;
             break;
     }
-    return GrBicubicEffect::Make(d->textureProxy(texIdx), SkMatrix::I(), kClampClamp, direction,
-                                 alphaType);
+    return GrBicubicEffect::Make(d->textureProxy(texIdx), d->textureProxyColorType(texIdx),
+                                 SkMatrix::I(), kClampClamp, direction, alphaType);
 }
 #endif
 
diff --git a/src/gpu/effects/GrBicubicEffect.h b/src/gpu/effects/GrBicubicEffect.h
index a19531a..a2dc249 100644
--- a/src/gpu/effects/GrBicubicEffect.h
+++ b/src/gpu/effects/GrBicubicEffect.h
@@ -45,27 +45,31 @@
      * Create a Mitchell filter effect with specified texture matrix with clamp wrap mode.
      */
     static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
+                                                     GrColorType srcColorType,
                                                      const SkMatrix& matrix,
                                                      Direction direction,
                                                      SkAlphaType alphaType) {
         static constexpr GrSamplerState::WrapMode kClampClamp[] = {
                 GrSamplerState::WrapMode::kClamp, GrSamplerState::WrapMode::kClamp};
-        return Make(std::move(proxy), matrix, kClampClamp, GrTextureDomain::kIgnore_Mode,
-                    GrTextureDomain::kIgnore_Mode, direction, alphaType);
+        return Make(std::move(proxy), srcColorType, matrix, kClampClamp,
+                    GrTextureDomain::kIgnore_Mode, GrTextureDomain::kIgnore_Mode, direction,
+                    alphaType);
     }
 
     /**
      * Create a Mitchell filter effect with specified texture matrix and x/y tile modes.
      */
     static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
+                                                     GrColorType srcColorType,
                                                      const SkMatrix& matrix,
                                                      const GrSamplerState::WrapMode wrapModes[2],
                                                      Direction direction,
                                                      SkAlphaType alphaType) {
         // Ignore the domain on x and y, since this factory relies solely on the wrap mode of the
         // sampler to constrain texture coordinates
-        return Make(std::move(proxy), matrix, wrapModes, GrTextureDomain::kIgnore_Mode,
-                    GrTextureDomain::kIgnore_Mode, direction, alphaType);
+        return Make(std::move(proxy), srcColorType, matrix, wrapModes,
+                    GrTextureDomain::kIgnore_Mode, GrTextureDomain::kIgnore_Mode, direction,
+                    alphaType);
     }
 
     /**
@@ -74,6 +78,7 @@
      * override the behavior of the sampler's tile mode (e.g. clamp to border unsupported).
      */
     static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
+                                                     GrColorType srcColorType,
                                                      const SkMatrix& matrix,
                                                      const GrSamplerState::WrapMode wrapModes[2],
                                                      GrTextureDomain::Mode modeX,
@@ -84,22 +89,24 @@
         SkRect resolvedDomain = domain ? *domain : GrTextureDomain::MakeTexelDomain(
                 SkIRect::MakeWH(proxy->width(), proxy->height()), modeX, modeY);
         return std::unique_ptr<GrFragmentProcessor>(
-                new GrBicubicEffect(std::move(proxy), matrix, resolvedDomain, wrapModes, modeX,
-                                    modeY, direction, alphaType));
+                new GrBicubicEffect(std::move(proxy), srcColorType, matrix, resolvedDomain,
+                                    wrapModes, modeX, modeY, direction, alphaType));
     }
 
     /**
      * Create a Mitchell filter effect with a texture matrix and a domain.
      */
     static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
+                                                     GrColorType srcColorType,
                                                      const SkMatrix& matrix,
                                                      const SkRect& domain,
                                                      Direction direction,
                                                      SkAlphaType alphaType) {
         static const GrSamplerState::WrapMode kClampClamp[] = {
                 GrSamplerState::WrapMode::kClamp, GrSamplerState::WrapMode::kClamp};
-        return Make(std::move(proxy), matrix, kClampClamp, GrTextureDomain::kClamp_Mode,
-                    GrTextureDomain::kClamp_Mode, direction, alphaType, &domain);
+        return Make(std::move(proxy), srcColorType, matrix, kClampClamp,
+                    GrTextureDomain::kClamp_Mode, GrTextureDomain::kClamp_Mode, direction,
+                    alphaType, &domain);
     }
 
     /**
@@ -113,9 +120,10 @@
                                  GrSamplerState::Filter* filterMode);
 
 private:
-    GrBicubicEffect(sk_sp<GrTextureProxy>, const SkMatrix& matrix, const SkRect& domain,
-                    const GrSamplerState::WrapMode wrapModes[2], GrTextureDomain::Mode modeX,
-                    GrTextureDomain::Mode modeY, Direction direction, SkAlphaType alphaType);
+    GrBicubicEffect(sk_sp<GrTextureProxy>, GrColorType srcColorType, const SkMatrix& matrix,
+                    const SkRect& domain, const GrSamplerState::WrapMode wrapModes[2],
+                    GrTextureDomain::Mode modeX, GrTextureDomain::Mode modeY, Direction direction,
+                    SkAlphaType alphaType);
     explicit GrBicubicEffect(const GrBicubicEffect&);
 
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
diff --git a/src/gpu/effects/GrConfigConversionEffect.fp b/src/gpu/effects/GrConfigConversionEffect.fp
index faaeeea..0387c3b 100644
--- a/src/gpu/effects/GrConfigConversionEffect.fp
+++ b/src/gpu/effects/GrConfigConversionEffect.fp
@@ -64,7 +64,7 @@
         // calling read pixels here. Thus the pixel data will be uploaded immediately and we don't
         // need to keep the pixel data alive in the proxy. Therefore the ReleaseProc is nullptr.
         sk_sp<SkImage> image = SkImage::MakeFromRaster(pixmap, nullptr, nullptr);
-
+        GrColorType dataColorType = SkColorTypeToGrColorType(image->colorType());
         sk_sp<GrTextureProxy> dataProxy = proxyProvider->createTextureProxy(std::move(image),
                                                                             1,
                                                                             SkBudgeted::kYes,
@@ -87,7 +87,7 @@
         std::unique_ptr<GrFragmentProcessor> upmToPM(
                 new GrConfigConversionEffect(PMConversion::kToPremul));
 
-        paint1.addColorTextureProcessor(dataProxy, SkMatrix::I());
+        paint1.addColorTextureProcessor(dataProxy, dataColorType, SkMatrix::I());
         paint1.addColorFragmentProcessor(pmToUPM->clone());
         paint1.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
@@ -101,14 +101,14 @@
         // draw
         tempRTC->discard();
 
-        paint2.addColorTextureProcessor(readRTC->asTextureProxyRef(), SkMatrix::I());
+        paint2.addColorTextureProcessor(readRTC->asTextureProxyRef(), kColorType, SkMatrix::I());
         paint2.addColorFragmentProcessor(std::move(upmToPM));
         paint2.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
         tempRTC->fillRectToRect(GrNoClip(), std::move(paint2), GrAA::kNo, SkMatrix::I(), kRect,
                                 kRect);
 
-        paint3.addColorTextureProcessor(tempRTC->asTextureProxyRef(), SkMatrix::I());
+        paint3.addColorTextureProcessor(tempRTC->asTextureProxyRef(), kColorType, SkMatrix::I());
         paint3.addColorFragmentProcessor(std::move(pmToUPM));
         paint3.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
diff --git a/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp b/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp
index 1c7e4db..fd70616 100644
--- a/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp
+++ b/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp
@@ -212,13 +212,14 @@
 
 GrGaussianConvolutionFragmentProcessor::GrGaussianConvolutionFragmentProcessor(
                                                             sk_sp<GrTextureProxy> proxy,
+                                                            GrColorType srcColorType,
                                                             Direction direction,
                                                             int radius,
                                                             float gaussianSigma,
                                                             GrTextureDomain::Mode mode,
                                                             int bounds[2])
         : INHERITED(kGrGaussianConvolutionFragmentProcessor_ClassID,
-                    ModulateForSamplerOptFlags(proxy->config(),
+                    ModulateForSamplerOptFlags(srcColorType,
                                                mode == GrTextureDomain::kDecal_Mode))
         , fCoordTransform(proxy.get())
         , fTextureSampler(std::move(proxy))
@@ -298,7 +299,7 @@
     float sigma = radius / 3.f;
 
     return GrGaussianConvolutionFragmentProcessor::Make(
-            d->textureProxy(texIdx),
+            std::move(proxy), d->textureProxyColorType(texIdx),
             dir, radius, sigma, static_cast<GrTextureDomain::Mode>(modeIdx), bounds);
 }
 #endif
diff --git a/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h b/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h
index 47a0ae2..843ed30 100644
--- a/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h
+++ b/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h
@@ -23,13 +23,14 @@
 
     /// Convolve with a Gaussian kernel
     static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
+                                                     GrColorType srcColorType,
                                                      Direction dir,
                                                      int halfWidth,
                                                      float gaussianSigma,
                                                      GrTextureDomain::Mode mode,
                                                      int* bounds) {
         return std::unique_ptr<GrFragmentProcessor>(new GrGaussianConvolutionFragmentProcessor(
-                std::move(proxy), dir, halfWidth, gaussianSigma, mode, bounds));
+                std::move(proxy), srcColorType, dir, halfWidth, gaussianSigma, mode, bounds));
     }
 
     const float* kernel() const { return fKernel; }
@@ -71,8 +72,8 @@
 
 private:
     /// Convolve with a Gaussian kernel
-    GrGaussianConvolutionFragmentProcessor(sk_sp<GrTextureProxy>, Direction,
-                                           int halfWidth, float gaussianSigma,
+    GrGaussianConvolutionFragmentProcessor(sk_sp<GrTextureProxy>, GrColorType srcColorType,
+                                           Direction, int halfWidth, float gaussianSigma,
                                            GrTextureDomain::Mode mode, int bounds[2]);
 
     explicit GrGaussianConvolutionFragmentProcessor(const GrGaussianConvolutionFragmentProcessor&);
diff --git a/src/gpu/effects/GrSimpleTextureEffect.fp b/src/gpu/effects/GrSimpleTextureEffect.fp
index 6c6d98b..1d827c1 100644
--- a/src/gpu/effects/GrSimpleTextureEffect.fp
+++ b/src/gpu/effects/GrSimpleTextureEffect.fp
@@ -6,6 +6,7 @@
  */
 
 in uniform sampler2D image;
+in GrColorType srcColorType;
 in half4x4 matrix;
 
 @constructorParams {
@@ -22,31 +23,34 @@
 
 @make {
     static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
+                                                     GrColorType srcColorType,
                                                      const SkMatrix& matrix) {
         return std::unique_ptr<GrFragmentProcessor>(
-            new GrSimpleTextureEffect(std::move(proxy), matrix,
+            new GrSimpleTextureEffect(std::move(proxy), srcColorType, matrix,
                     GrSamplerState(GrSamplerState::WrapMode::kClamp, GrSamplerState::Filter::kNearest)));
     }
 
     /* clamp mode */
     static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
+                                                     GrColorType srcColorType,
                                                      const SkMatrix& matrix,
                                                      GrSamplerState::Filter filter) {
         return std::unique_ptr<GrFragmentProcessor>(
-            new GrSimpleTextureEffect(std::move(proxy), matrix,
+            new GrSimpleTextureEffect(std::move(proxy), srcColorType, matrix,
                                       GrSamplerState(GrSamplerState::WrapMode::kClamp, filter)));
      }
 
     static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
+                                                     GrColorType srcColorType,
                                                      const SkMatrix& matrix,
                                                      const GrSamplerState& p) {
         return std::unique_ptr<GrFragmentProcessor>(
-            new GrSimpleTextureEffect(std::move(proxy), matrix, p));
+            new GrSimpleTextureEffect(std::move(proxy), srcColorType, matrix, p));
     }
 }
 
 @optimizationFlags {
-    ModulateForSamplerOptFlags(image->config(),
+    ModulateForSamplerOptFlags(srcColorType,
             samplerParams.wrapModeX() == GrSamplerState::WrapMode::kClampToBorder ||
             samplerParams.wrapModeY() == GrSamplerState::WrapMode::kClampToBorder)
 }
@@ -72,5 +76,6 @@
                                                                : GrSamplerState::Filter::kNearest);
 
     const SkMatrix& matrix = GrTest::TestMatrix(testData->fRandom);
-    return GrSimpleTextureEffect::Make(testData->textureProxy(texIdx), matrix, params);
+    return GrSimpleTextureEffect::Make(testData->textureProxy(texIdx),
+                                       testData->textureProxyColorType(texIdx), matrix, params);
 }
diff --git a/src/gpu/effects/GrTextureDomain.cpp b/src/gpu/effects/GrTextureDomain.cpp
index 852c9d7..25b5bb3 100644
--- a/src/gpu/effects/GrTextureDomain.cpp
+++ b/src/gpu/effects/GrTextureDomain.cpp
@@ -252,16 +252,18 @@
 
 std::unique_ptr<GrFragmentProcessor> GrTextureDomainEffect::Make(
         sk_sp<GrTextureProxy> proxy,
+        GrColorType srcColorType,
         const SkMatrix& matrix,
         const SkRect& domain,
         GrTextureDomain::Mode mode,
         GrSamplerState::Filter filterMode) {
-    return Make(std::move(proxy), matrix, domain, mode, mode,
+    return Make(std::move(proxy), srcColorType, matrix, domain, mode, mode,
                 GrSamplerState(GrSamplerState::WrapMode::kClamp, filterMode));
 }
 
 std::unique_ptr<GrFragmentProcessor> GrTextureDomainEffect::Make(
         sk_sp<GrTextureProxy> proxy,
+        GrColorType srcColorType,
         const SkMatrix& matrix,
         const SkRect& domain,
         GrTextureDomain::Mode modeX,
@@ -272,17 +274,18 @@
     // with the sampler modes and the proxy is the same size as the domain. It's a lot easier for
     // calling code to detect these cases and handle it themselves.
     return std::unique_ptr<GrFragmentProcessor>(new GrTextureDomainEffect(
-            std::move(proxy), matrix, domain, modeX, modeY, sampler));
+            std::move(proxy), srcColorType, matrix, domain, modeX, modeY, sampler));
 }
 
 GrTextureDomainEffect::GrTextureDomainEffect(sk_sp<GrTextureProxy> proxy,
+                                             GrColorType srcColorType,
                                              const SkMatrix& matrix,
                                              const SkRect& domain,
                                              GrTextureDomain::Mode modeX,
                                              GrTextureDomain::Mode modeY,
                                              const GrSamplerState& sampler)
         : INHERITED(kGrTextureDomainEffect_ClassID,
-                    ModulateForSamplerOptFlags(proxy->config(),
+                    ModulateForSamplerOptFlags(srcColorType,
                             GrTextureDomain::IsDecalSampled(sampler, modeX, modeY)))
         , fCoordTransform(matrix, proxy.get())
         , fTextureDomain(proxy.get(), domain, modeX, modeY)
@@ -373,6 +376,7 @@
             d->fRandom->nextBool() : false;
     return GrTextureDomainEffect::Make(
             std::move(proxy),
+            d->textureProxyColorType(texIdx),
             matrix,
             domain,
             modeX,
diff --git a/src/gpu/effects/GrTextureDomain.h b/src/gpu/effects/GrTextureDomain.h
index 4b21b97..96c2d20 100644
--- a/src/gpu/effects/GrTextureDomain.h
+++ b/src/gpu/effects/GrTextureDomain.h
@@ -188,12 +188,14 @@
 class GrTextureDomainEffect : public GrFragmentProcessor {
 public:
     static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy>,
+                                                     GrColorType srcColorType,
                                                      const SkMatrix&,
                                                      const SkRect& domain,
                                                      GrTextureDomain::Mode mode,
                                                      GrSamplerState::Filter filterMode);
 
     static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy>,
+                                                     GrColorType srcColorType,
                                                      const SkMatrix&,
                                                      const SkRect& domain,
                                                      GrTextureDomain::Mode modeX,
@@ -223,6 +225,7 @@
     TextureSampler fTextureSampler;
 
     GrTextureDomainEffect(sk_sp<GrTextureProxy>,
+                          GrColorType srcColorType,
                           const SkMatrix&,
                           const SkRect& domain,
                           GrTextureDomain::Mode modeX,
diff --git a/src/gpu/effects/generated/GrConfigConversionEffect.h b/src/gpu/effects/generated/GrConfigConversionEffect.h
index 5823a26..acbc4cc 100644
--- a/src/gpu/effects/generated/GrConfigConversionEffect.h
+++ b/src/gpu/effects/generated/GrConfigConversionEffect.h
@@ -68,7 +68,7 @@
         // calling read pixels here. Thus the pixel data will be uploaded immediately and we don't
         // need to keep the pixel data alive in the proxy. Therefore the ReleaseProc is nullptr.
         sk_sp<SkImage> image = SkImage::MakeFromRaster(pixmap, nullptr, nullptr);
-
+        GrColorType dataColorType = SkColorTypeToGrColorType(image->colorType());
         sk_sp<GrTextureProxy> dataProxy = proxyProvider->createTextureProxy(
                 std::move(image), 1, SkBudgeted::kYes, SkBackingFit::kExact);
         if (!dataProxy) {
@@ -89,7 +89,7 @@
         std::unique_ptr<GrFragmentProcessor> upmToPM(
                 new GrConfigConversionEffect(PMConversion::kToPremul));
 
-        paint1.addColorTextureProcessor(dataProxy, SkMatrix::I());
+        paint1.addColorTextureProcessor(dataProxy, dataColorType, SkMatrix::I());
         paint1.addColorFragmentProcessor(pmToUPM->clone());
         paint1.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
@@ -103,14 +103,14 @@
         // draw
         tempRTC->discard();
 
-        paint2.addColorTextureProcessor(readRTC->asTextureProxyRef(), SkMatrix::I());
+        paint2.addColorTextureProcessor(readRTC->asTextureProxyRef(), kColorType, SkMatrix::I());
         paint2.addColorFragmentProcessor(std::move(upmToPM));
         paint2.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
         tempRTC->fillRectToRect(GrNoClip(), std::move(paint2), GrAA::kNo, SkMatrix::I(), kRect,
                                 kRect);
 
-        paint3.addColorTextureProcessor(tempRTC->asTextureProxyRef(), SkMatrix::I());
+        paint3.addColorTextureProcessor(tempRTC->asTextureProxyRef(), kColorType, SkMatrix::I());
         paint3.addColorFragmentProcessor(std::move(pmToUPM));
         paint3.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
diff --git a/src/gpu/effects/generated/GrSimpleTextureEffect.cpp b/src/gpu/effects/generated/GrSimpleTextureEffect.cpp
index 5f57e2e..6de8032 100644
--- a/src/gpu/effects/generated/GrSimpleTextureEffect.cpp
+++ b/src/gpu/effects/generated/GrSimpleTextureEffect.cpp
@@ -23,6 +23,8 @@
         GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
         const GrSimpleTextureEffect& _outer = args.fFp.cast<GrSimpleTextureEffect>();
         (void)_outer;
+        auto srcColorType = _outer.srcColorType;
+        (void)srcColorType;
         auto matrix = _outer.matrix;
         (void)matrix;
         SkString sk_TransformedCoords2D_0 =
@@ -48,6 +50,7 @@
     const GrSimpleTextureEffect& that = other.cast<GrSimpleTextureEffect>();
     (void)that;
     if (image != that.image) return false;
+    if (srcColorType != that.srcColorType) return false;
     if (matrix != that.matrix) return false;
     return true;
 }
@@ -55,6 +58,7 @@
         : INHERITED(kGrSimpleTextureEffect_ClassID, src.optimizationFlags())
         , imageCoordTransform(src.imageCoordTransform)
         , image(src.image)
+        , srcColorType(src.srcColorType)
         , matrix(src.matrix) {
     this->setTextureSamplerCnt(1);
     this->addCoordTransform(&imageCoordTransform);
@@ -86,6 +90,7 @@
                                              : GrSamplerState::Filter::kNearest);
 
     const SkMatrix& matrix = GrTest::TestMatrix(testData->fRandom);
-    return GrSimpleTextureEffect::Make(testData->textureProxy(texIdx), matrix, params);
+    return GrSimpleTextureEffect::Make(testData->textureProxy(texIdx),
+                                       testData->textureProxyColorType(texIdx), matrix, params);
 }
 #endif
diff --git a/src/gpu/effects/generated/GrSimpleTextureEffect.h b/src/gpu/effects/generated/GrSimpleTextureEffect.h
index 556c2c3..ac2ac73 100644
--- a/src/gpu/effects/generated/GrSimpleTextureEffect.h
+++ b/src/gpu/effects/generated/GrSimpleTextureEffect.h
@@ -17,47 +17,52 @@
 class GrSimpleTextureEffect : public GrFragmentProcessor {
 public:
     static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
+                                                     GrColorType srcColorType,
                                                      const SkMatrix& matrix) {
         return std::unique_ptr<GrFragmentProcessor>(
-                new GrSimpleTextureEffect(std::move(proxy), matrix,
+                new GrSimpleTextureEffect(std::move(proxy), srcColorType, matrix,
                                           GrSamplerState(GrSamplerState::WrapMode::kClamp,
                                                          GrSamplerState::Filter::kNearest)));
     }
 
     /* clamp mode */
     static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
+                                                     GrColorType srcColorType,
                                                      const SkMatrix& matrix,
                                                      GrSamplerState::Filter filter) {
         return std::unique_ptr<GrFragmentProcessor>(new GrSimpleTextureEffect(
-                std::move(proxy), matrix,
+                std::move(proxy), srcColorType, matrix,
                 GrSamplerState(GrSamplerState::WrapMode::kClamp, filter)));
     }
 
     static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
+                                                     GrColorType srcColorType,
                                                      const SkMatrix& matrix,
                                                      const GrSamplerState& p) {
         return std::unique_ptr<GrFragmentProcessor>(
-                new GrSimpleTextureEffect(std::move(proxy), matrix, p));
+                new GrSimpleTextureEffect(std::move(proxy), srcColorType, matrix, p));
     }
     GrSimpleTextureEffect(const GrSimpleTextureEffect& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "SimpleTextureEffect"; }
     GrCoordTransform imageCoordTransform;
     TextureSampler image;
+    GrColorType srcColorType;
     SkMatrix44 matrix;
 
 private:
-    GrSimpleTextureEffect(sk_sp<GrTextureProxy> image, SkMatrix44 matrix,
+    GrSimpleTextureEffect(sk_sp<GrTextureProxy> image, GrColorType srcColorType, SkMatrix44 matrix,
                           GrSamplerState samplerParams)
             : INHERITED(kGrSimpleTextureEffect_ClassID,
                         (OptimizationFlags)ModulateForSamplerOptFlags(
-                                image->config(),
+                                srcColorType,
                                 samplerParams.wrapModeX() ==
                                                 GrSamplerState::WrapMode::kClampToBorder ||
                                         samplerParams.wrapModeY() ==
                                                 GrSamplerState::WrapMode::kClampToBorder))
             , imageCoordTransform(matrix, image.get())
             , image(std::move(image), samplerParams)
+            , srcColorType(srcColorType)
             , matrix(matrix) {
         this->setTextureSamplerCnt(1);
         this->addCoordTransform(&imageCoordTransform);
diff --git a/src/gpu/ops/GrLatticeOp.cpp b/src/gpu/ops/GrLatticeOp.cpp
index a0b0296..adcfe8c 100644
--- a/src/gpu/ops/GrLatticeOp.cpp
+++ b/src/gpu/ops/GrLatticeOp.cpp
@@ -138,24 +138,27 @@
                                           GrPaint&& paint,
                                           const SkMatrix& viewMatrix,
                                           sk_sp<GrTextureProxy> proxy,
+                                          GrColorType srcColorType,
                                           sk_sp<GrColorSpaceXform> colorSpaceXForm,
                                           GrSamplerState::Filter filter,
                                           std::unique_ptr<SkLatticeIter> iter,
                                           const SkRect& dst) {
         SkASSERT(proxy);
         return Helper::FactoryHelper<NonAALatticeOp>(context, std::move(paint), viewMatrix,
-                                                     std::move(proxy),
+                                                     std::move(proxy), srcColorType,
                                                      std::move(colorSpaceXForm), filter,
                                                      std::move(iter), dst);
     }
 
     NonAALatticeOp(Helper::MakeArgs& helperArgs, const SkPMColor4f& color,
                    const SkMatrix& viewMatrix, sk_sp<GrTextureProxy> proxy,
-                   sk_sp<GrColorSpaceXform> colorSpaceXform, GrSamplerState::Filter filter,
-                   std::unique_ptr<SkLatticeIter> iter, const SkRect& dst)
+                   GrColorType srcColorType, sk_sp<GrColorSpaceXform> colorSpaceXform,
+                   GrSamplerState::Filter filter, std::unique_ptr<SkLatticeIter> iter,
+                   const SkRect& dst)
             : INHERITED(ClassID())
             , fHelper(helperArgs, GrAAType::kNone)
             , fProxy(std::move(proxy))
+            , fSrcColorType(srcColorType)
             , fColorSpaceXform(std::move(colorSpaceXform))
             , fFilter(filter) {
         Patch& patch = fPatches.push_back();
@@ -197,7 +200,7 @@
     GrProcessorSet::Analysis finalize(
             const GrCaps& caps, const GrAppliedClip* clip, bool hasMixedSampledCoverage,
             GrClampType clampType) override {
-        auto opaque = fPatches[0].fColor.isOpaque() && GrPixelConfigIsOpaque(fProxy->config())
+        auto opaque = fPatches[0].fColor.isOpaque() && !GrColorTypeHasAlpha(fSrcColorType)
                               ? GrProcessorAnalysisColor::Opaque::kYes
                               : GrProcessorAnalysisColor::Opaque::kNo;
         auto analysisColor = GrProcessorAnalysisColor(opaque);
@@ -328,6 +331,7 @@
     Helper fHelper;
     SkSTArray<1, Patch, true> fPatches;
     sk_sp<GrTextureProxy> fProxy;
+    GrColorType fSrcColorType;
     sk_sp<GrColorSpaceXform> fColorSpaceXform;
     GrSamplerState::Filter fFilter;
     bool fWideColor;
@@ -342,12 +346,14 @@
                                     GrPaint&& paint,
                                     const SkMatrix& viewMatrix,
                                     sk_sp<GrTextureProxy> proxy,
+                                    GrColorType srcColorType,
                                     sk_sp<GrColorSpaceXform> colorSpaceXform,
                                     GrSamplerState::Filter filter,
                                     std::unique_ptr<SkLatticeIter> iter,
                                     const SkRect& dst) {
     return NonAALatticeOp::Make(context, std::move(paint), viewMatrix, std::move(proxy),
-                                std::move(colorSpaceXform), filter, std::move(iter), dst);
+                                srcColorType, std::move(colorSpaceXform), filter, std::move(iter),
+                                dst);
 }
 };
 
@@ -466,7 +472,8 @@
     GrSamplerState::Filter filter =
             random->nextBool() ? GrSamplerState::Filter::kNearest : GrSamplerState::Filter::kBilerp;
     return NonAALatticeOp::Make(context, std::move(paint), viewMatrix, std::move(proxy),
-                                std::move(csxf), filter, std::move(iter), dst);
+                                GrColorType::kRGBA_8888, std::move(csxf), filter, std::move(iter),
+                                dst);
 }
 
 #endif
diff --git a/src/gpu/ops/GrLatticeOp.h b/src/gpu/ops/GrLatticeOp.h
index 96898ac..1ea5725 100644
--- a/src/gpu/ops/GrLatticeOp.h
+++ b/src/gpu/ops/GrLatticeOp.h
@@ -26,6 +26,7 @@
                                     GrPaint&&,
                                     const SkMatrix& viewMatrix,
                                     sk_sp<GrTextureProxy>,
+                                    GrColorType srcColorType,
                                     sk_sp<GrColorSpaceXform>,
                                     GrSamplerState::Filter,
                                     std::unique_ptr<SkLatticeIter>,
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index 669c935..880a751 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -646,6 +646,7 @@
 
 std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
                                sk_sp<GrTextureProxy> proxy,
+                               GrColorType srcColorType,
                                sk_sp<GrColorSpaceXform> textureXform,
                                GrSamplerState::Filter filter,
                                const SkPMColor4f& color,
@@ -683,10 +684,10 @@
             SkRect correctedDomain;
             compute_domain(Domain::kYes, filter, kTopLeft_GrSurfaceOrigin, *domain,
                            1.f, 1.f, proxy->height(), &correctedDomain);
-            fp = GrTextureDomainEffect::Make(std::move(proxy), SkMatrix::I(), correctedDomain,
-                                             GrTextureDomain::kClamp_Mode, filter);
+            fp = GrTextureDomainEffect::Make(std::move(proxy), srcColorType, SkMatrix::I(),
+                                             correctedDomain, GrTextureDomain::kClamp_Mode, filter);
         } else {
-            fp = GrSimpleTextureEffect::Make(std::move(proxy), SkMatrix::I(), filter);
+            fp = GrSimpleTextureEffect::Make(std::move(proxy), srcColorType, SkMatrix::I(), filter);
         }
         fp = GrColorSpaceXformEffect::Make(std::move(fp), std::move(textureXform));
         paint.addColorFragmentProcessor(std::move(fp));
@@ -765,10 +766,10 @@
     aaFlags |= random->nextBool() ? GrQuadAAFlags::kBottom : GrQuadAAFlags::kNone;
     bool useDomain = random->nextBool();
     auto saturate = random->nextBool() ? GrTextureOp::Saturate::kYes : GrTextureOp::Saturate::kNo;
-    return GrTextureOp::Make(context, std::move(proxy), std::move(texXform), filter, color,
-                             saturate, SkBlendMode::kSrcOver, aaType, aaFlags,
-                             GrQuad::MakeFromRect(rect, viewMatrix), GrQuad(srcRect),
-                             useDomain ? &srcRect : nullptr);
+    return GrTextureOp::Make(context, std::move(proxy), GrColorType::kRGBA_8888,
+                             std::move(texXform), filter, color, saturate, SkBlendMode::kSrcOver,
+                             aaType, aaFlags, GrQuad::MakeFromRect(rect, viewMatrix),
+                             GrQuad(srcRect), useDomain ? &srcRect : nullptr);
 }
 
 #endif
diff --git a/src/gpu/ops/GrTextureOp.h b/src/gpu/ops/GrTextureOp.h
index 1e85c29..da7a6b4 100644
--- a/src/gpu/ops/GrTextureOp.h
+++ b/src/gpu/ops/GrTextureOp.h
@@ -41,6 +41,7 @@
  */
 std::unique_ptr<GrDrawOp> Make(GrRecordingContext*,
                                sk_sp<GrTextureProxy>,
+                               GrColorType srcColorType,
                                sk_sp<GrColorSpaceXform>,
                                GrSamplerState::Filter,
                                const SkPMColor4f&,
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index 50af596..30254e5 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -93,7 +93,8 @@
 
     GrPaint paint;
     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-    paint.addColorTextureProcessor(std::move(proxy), SkMatrix::I());
+    paint.addColorTextureProcessor(std::move(proxy), SkColorTypeToGrColorType(this->colorType()),
+                                   SkMatrix::I());
     if (xform) {
         paint.addColorFragmentProcessor(std::move(xform));
     }
diff --git a/src/image/SkImage_GpuBase.cpp b/src/image/SkImage_GpuBase.cpp
index 54cd000..7d906f0 100644
--- a/src/image/SkImage_GpuBase.cpp
+++ b/src/image/SkImage_GpuBase.cpp
@@ -117,9 +117,10 @@
     }
 
     sk_sp<GrSurfaceProxy> proxy = this->asTextureProxyRef(context);
+    GrColorType srcColorType = SkColorTypeToGrColorType(this->colorType());
 
     sk_sp<GrTextureProxy> copyProxy = GrSurfaceProxy::Copy(
-            context, proxy.get(), GrMipMapped::kNo, subset, SkBackingFit::kExact,
+            context, proxy.get(), srcColorType, GrMipMapped::kNo, subset, SkBackingFit::kExact,
             proxy->isBudgeted());
 
     if (!copyProxy) {
diff --git a/src/image/SkImage_GpuYUVA.cpp b/src/image/SkImage_GpuYUVA.cpp
index 978060f..03a7cac 100644
--- a/src/image/SkImage_GpuYUVA.cpp
+++ b/src/image/SkImage_GpuYUVA.cpp
@@ -31,8 +31,9 @@
 
 SkImage_GpuYUVA::SkImage_GpuYUVA(sk_sp<GrContext> context, int width, int height, uint32_t uniqueID,
                                  SkYUVColorSpace colorSpace, sk_sp<GrTextureProxy> proxies[],
-                                 int numProxies, const SkYUVAIndex yuvaIndices[4],
-                                 GrSurfaceOrigin origin, sk_sp<SkColorSpace> imageColorSpace)
+                                 GrColorType proxyColorTypes[], int numProxies,
+                                 const SkYUVAIndex yuvaIndices[4], GrSurfaceOrigin origin,
+                                 sk_sp<SkColorSpace> imageColorSpace)
         : INHERITED(std::move(context), width, height, uniqueID, kAssumedColorType,
                     // If an alpha channel is present we always switch to kPremul. This is because,
                     // although the planar data is always un-premul, the final interleaved RGB image
@@ -48,6 +49,7 @@
 
     for (int i = 0; i < numProxies; ++i) {
         fProxies[i] = std::move(proxies[i]);
+        fProxyColorTypes[i] = proxyColorTypes[i];
     }
     memcpy(fYUVAIndices, yuvaIndices, 4*sizeof(SkYUVAIndex));
 }
@@ -76,6 +78,7 @@
     } else {
         for (int i = 0; i < fNumProxies; ++i) {
             fProxies[i] = image->fProxies[i];  // we ref in this case, not move
+            fProxyColorTypes[i] = image->fProxyColorTypes[i];
         }
     }
     memcpy(fYUVAIndices, image->fYUVAIndices, 4 * sizeof(SkYUVAIndex));
@@ -97,7 +100,8 @@
                                                     fProxies[i].get(),
                                                     GrSamplerState::Filter::kMipMap,
                                                     &copyParams)) {
-            auto mippedProxy = GrCopyBaseMipMapToTextureProxy(context, fProxies[i].get());
+            auto mippedProxy = GrCopyBaseMipMapToTextureProxy(context, fProxies[i].get(),
+                                                              fProxyColorTypes[i]);
             if (!mippedProxy) {
                 return false;
             }
@@ -178,7 +182,8 @@
     }
 
     // need to generate mips for the proxy
-    if (auto mippedProxy = GrCopyBaseMipMapToTextureProxy(context, proxy.get())) {
+    GrColorType srcColorType = SkColorTypeToGrColorType(this->colorType());
+    if (auto mippedProxy = GrCopyBaseMipMapToTextureProxy(context, proxy.get(), srcColorType)) {
         fRGBProxy = mippedProxy;
         return mippedProxy;
     }
@@ -209,8 +214,9 @@
 
 sk_sp<SkImage> SkImage_GpuYUVA::onReinterpretColorSpace(sk_sp<SkColorSpace> newCS) const {
     return sk_make_sp<SkImage_GpuYUVA>(fContext, this->width(), this->height(),
-                                       kNeedNewImageUniqueID, fYUVColorSpace, fProxies, fNumProxies,
-                                       fYUVAIndices, fOrigin, std::move(newCS));
+                                       kNeedNewImageUniqueID, fYUVColorSpace, fProxies,
+                                       fProxyColorTypes, fNumProxies, fYUVAIndices, fOrigin,
+                                       std::move(newCS));
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////////////
@@ -232,10 +238,16 @@
                                                  imageOrigin, tempTextureProxies)) {
         return nullptr;
     }
+    GrColorType proxyColorTypes[4];
+    for (int i = 0; i < numTextures; ++i) {
+        proxyColorTypes[i] = ctx->priv().caps()->getYUVAColorTypeFromBackendFormat(
+                yuvaTextures[i].getBackendFormat(), yuvaIndices[3].fIndex == i);
+    }
 
     return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(ctx), imageSize.width(), imageSize.height(),
                                        kNeedNewImageUniqueID, colorSpace, tempTextureProxies,
-                                       numTextures, yuvaIndices, imageOrigin, imageColorSpace);
+                                       proxyColorTypes, numTextures, yuvaIndices, imageOrigin,
+                                       imageColorSpace);
 }
 
 sk_sp<SkImage> SkImage::MakeFromYUVAPixmaps(
@@ -258,6 +270,7 @@
     // Make proxies
     GrProxyProvider* proxyProvider = context->priv().proxyProvider();
     sk_sp<GrTextureProxy> tempTextureProxies[4];
+    GrColorType proxyColorTypes[4];
     for (int i = 0; i < numPixmaps; ++i) {
         const SkPixmap* pixmap = &yuvaPixmaps[i];
         SkAutoPixmapStorage resized;
@@ -284,11 +297,13 @@
         if (!tempTextureProxies[i]) {
             return nullptr;
         }
+        proxyColorTypes[i] = SkColorTypeToGrColorType(bmp.colorType());
     }
 
     return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(context), imageSize.width(), imageSize.height(),
                                        kNeedNewImageUniqueID, yuvColorSpace, tempTextureProxies,
-                                       numPixmaps, yuvaIndices, imageOrigin, imageColorSpace);
+                                       proxyColorTypes, numPixmaps, yuvaIndices, imageOrigin,
+                                       imageColorSpace);
 }
 
 
@@ -358,6 +373,7 @@
 
     // Get lazy proxies
     sk_sp<GrTextureProxy> proxies[4];
+    GrColorType proxyColorTypes[4];
     for (int texIdx = 0; texIdx < numTextures; ++texIdx) {
         GrColorType colorType = context->priv().caps()->getYUVAColorTypeFromBackendFormat(
                                                                 yuvaFormats[texIdx],
@@ -374,9 +390,11 @@
         if (!proxies[texIdx]) {
             return nullptr;
         }
+        proxyColorTypes[texIdx] = colorType;
     }
 
     return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(context), imageWidth, imageHeight,
-                                       kNeedNewImageUniqueID, yuvColorSpace, proxies, numTextures,
-                                       yuvaIndices, imageOrigin, std::move(imageColorSpace));
+                                       kNeedNewImageUniqueID, yuvColorSpace, proxies,
+                                       proxyColorTypes, numTextures, yuvaIndices, imageOrigin,
+                                       std::move(imageColorSpace));
 }
diff --git a/src/image/SkImage_GpuYUVA.h b/src/image/SkImage_GpuYUVA.h
index 2ec46eb..eac04e4 100644
--- a/src/image/SkImage_GpuYUVA.h
+++ b/src/image/SkImage_GpuYUVA.h
@@ -25,8 +25,8 @@
     friend class GrYUVAImageTextureMaker;
 
     SkImage_GpuYUVA(sk_sp<GrContext>, int width, int height, uint32_t uniqueID, SkYUVColorSpace,
-                    sk_sp<GrTextureProxy> proxies[], int numProxies, const SkYUVAIndex[4],
-                    GrSurfaceOrigin, sk_sp<SkColorSpace>);
+                    sk_sp<GrTextureProxy> proxies[], GrColorType proxyColorTypes[], int numProxies,
+                    const SkYUVAIndex[4], GrSurfaceOrigin, sk_sp<SkColorSpace>);
     ~SkImage_GpuYUVA() override;
 
     GrSemaphoresSubmitted onFlush(GrContext*, const GrFlushInfo&) override;
@@ -82,6 +82,7 @@
     // This array will usually only be sparsely populated.
     // The actual non-null fields are dictated by the 'fYUVAIndices' indices
     mutable sk_sp<GrTextureProxy>    fProxies[4];
+    mutable GrColorType              fProxyColorTypes[4];
     int                              fNumProxies;
     SkYUVAIndex                      fYUVAIndices[4];
     const SkYUVColorSpace            fYUVColorSpace;
diff --git a/src/image/SkImage_Lazy.cpp b/src/image/SkImage_Lazy.cpp
index 74e3185..022ba40 100644
--- a/src/image/SkImage_Lazy.cpp
+++ b/src/image/SkImage_Lazy.cpp
@@ -537,7 +537,8 @@
         SkASSERT(GrMipMapped::kNo == proxy->mipMapped());
         *fUniqueKeyInvalidatedMessages.append() =
                 new GrUniqueKeyInvalidatedMessage(key, ctx->priv().contextID());
-        if (auto mippedProxy = GrCopyBaseMipMapToTextureProxy(ctx, proxy.get())) {
+        GrColorType srcColorType = SkColorTypeToGrColorType(this->colorType());
+        if (auto mippedProxy = GrCopyBaseMipMapToTextureProxy(ctx, proxy.get(), srcColorType)) {
             set_key_on_proxy(proxyProvider, mippedProxy.get(), proxy.get(), key);
             return mippedProxy;
         }
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index 6eb3fda..623c54e 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -104,16 +104,16 @@
     sk_sp<GrTextureProxy> srcProxy = rtc->asTextureProxyRef();
 
     if (subset) {
-        srcProxy = GrSurfaceProxy::Copy(ctx, rtc->asSurfaceProxy(), rtc->mipMapped(), *subset,
-                                        SkBackingFit::kExact, budgeted);
+        srcProxy = GrSurfaceProxy::Copy(ctx, rtc->asSurfaceProxy(), rtc->colorInfo().colorType(),
+                                        rtc->mipMapped(), *subset, SkBackingFit::kExact, budgeted);
     } else if (!srcProxy || rtc->priv().refsWrappedObjects()) {
         // If the original render target is a buffer originally created by the client, then we don't
         // want to ever retarget the SkSurface at another buffer we create. Force a copy now to avoid
         // copy-on-write.
         SkASSERT(rtc->origin() == rtc->asSurfaceProxy()->origin());
 
-        srcProxy = GrSurfaceProxy::Copy(ctx, rtc->asSurfaceProxy(), rtc->mipMapped(),
-                                        SkBackingFit::kExact, budgeted);
+        srcProxy = GrSurfaceProxy::Copy(ctx, rtc->asSurfaceProxy(), rtc->colorInfo().colorType(),
+                                        rtc->mipMapped(), SkBackingFit::kExact, budgeted);
     }
 
     const SkImageInfo info = fDevice->imageInfo();
diff --git a/src/shaders/SkImageShader.cpp b/src/shaders/SkImageShader.cpp
index ae00be4..5bc13e5 100644
--- a/src/shaders/SkImageShader.cpp
+++ b/src/shaders/SkImageShader.cpp
@@ -228,7 +228,7 @@
         return nullptr;
     }
 
-    bool isAlphaOnly = SkColorTypeIsAlphaOnly(fImage->colorType());
+    GrColorType srcColorType = SkColorTypeToGrColorType(fImage->colorType());
 
     lmInverse.postScale(scaleAdjust[0], scaleAdjust[1]);
 
@@ -237,21 +237,24 @@
         // domainX and domainY will properly apply the decal effect with the texture domain used in
         // the bicubic filter if clamp to border was unsupported in hardware
         static constexpr auto kDir = GrBicubicEffect::Direction::kXY;
-        inner = GrBicubicEffect::Make(std::move(proxy), lmInverse, wrapModes, domainX, domainY,
-                                      kDir, fImage->alphaType());
+        inner = GrBicubicEffect::Make(std::move(proxy), srcColorType, lmInverse, wrapModes, domainX,
+                                      domainY, kDir, fImage->alphaType());
     } else {
         if (domainX != GrTextureDomain::kIgnore_Mode || domainY != GrTextureDomain::kIgnore_Mode) {
             SkRect domain = GrTextureDomain::MakeTexelDomain(
                     SkIRect::MakeWH(proxy->width(), proxy->height()),
                     domainX, domainY);
-            inner = GrTextureDomainEffect::Make(std::move(proxy), lmInverse, domain,
+            inner = GrTextureDomainEffect::Make(std::move(proxy), srcColorType, lmInverse, domain,
                                                 domainX, domainY, samplerState);
         } else {
-            inner = GrSimpleTextureEffect::Make(std::move(proxy), lmInverse, samplerState);
+            inner = GrSimpleTextureEffect::Make(std::move(proxy), srcColorType, lmInverse,
+                                                samplerState);
         }
     }
     inner = GrColorSpaceXformEffect::Make(std::move(inner), fImage->colorSpace(),
                                           fImage->alphaType(), args.fDstColorInfo->colorSpace());
+
+    bool isAlphaOnly = SkColorTypeIsAlphaOnly(fImage->colorType());
     if (isAlphaOnly) {
         return inner;
     } else if (args.fInputColorIsOpaque) {
diff --git a/src/sksl/sksl_enums.inc b/src/sksl/sksl_enums.inc
index eb60b3b..bda910b 100644
--- a/src/sksl/sksl_enums.inc
+++ b/src/sksl/sksl_enums.inc
@@ -32,4 +32,37 @@
     kPMConversionCnt = 2
 };
 
+enum class GrColorType {
+    kUnknown,
+    kAlpha_8,
+    kBGR_565,
+    kABGR_4444,  // This name differs from SkColorType. kARGB_4444_SkColorType is misnamed.
+    kRGBA_8888,
+    kRGBA_8888_SRGB,
+    kRGB_888x,
+    kRG_88,
+    kBGRA_8888,
+    kRGBA_1010102,
+    kGray_8,
+    kAlpha_F16,
+    kRGBA_F16,
+    kRGBA_F16_Clamped,
+    kRGBA_F32,
+
+    kAlpha_16,
+    kRG_1616,
+    kRG_F16,
+    kRGBA_16161616,
+
+    // Unusual formats that come up after reading back in cases where we are reassigning the meaning
+    // of a texture format's channels to use for a particular color format but have to read back the
+    // data to a full RGBA quadruple. (e.g. using a R8 texture format as A8 color type but the API
+    // only supports reading to RGBA8.) None of these have SkColorType equivalents.
+    kAlpha_8xxx,
+    kAlpha_F32xxx,
+    kGray_8xxx,
+
+    kLast = kGray_8xxx
+};
+
 )"
diff --git a/tests/CopySurfaceTest.cpp b/tests/CopySurfaceTest.cpp
index 1fb5dba..11f173e 100644
--- a/tests/CopySurfaceTest.cpp
+++ b/tests/CopySurfaceTest.cpp
@@ -104,9 +104,10 @@
                                     }
                                 }
 
+                                GrColorType grColorType = SkColorTypeToGrColorType(ii.colorType());
                                 auto dstContext = context->priv().makeWrappedSurfaceContext(
                                         std::move(dst),
-                                        SkColorTypeToGrColorType(ii.colorType()),
+                                        grColorType,
                                         ii.alphaType());
 
                                 bool result = false;
@@ -115,7 +116,7 @@
                                 } else if (dRenderable == GrRenderable::kYes) {
                                     SkASSERT(dstContext->asRenderTargetContext());
                                     result = dstContext->asRenderTargetContext()->blitTexture(
-                                            src.get(), srcRect, dstPoint);
+                                            src.get(), grColorType, srcRect, dstPoint);
                                 }
 
                                 bool expectedResult = true;
diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp
index 98c4197..c1c3dbd 100644
--- a/tests/GLProgramsTest.cpp
+++ b/tests/GLProgramsTest.cpp
@@ -261,6 +261,7 @@
     GrProxyProvider* proxyProvider = context->priv().proxyProvider();
 
     sk_sp<GrTextureProxy> proxies[2];
+    GrColorType proxyColorTypes[2];
 
     // setup dummy textures
     GrMipMapped mipMapped = GrMipMapped(context->priv().caps()->mipMapSupport());
@@ -276,6 +277,7 @@
                                                 kBottomLeft_GrSurfaceOrigin, mipMapped,
                                                 SkBackingFit::kExact, SkBudgeted::kNo,
                                                 GrProtected::kNo, GrInternalSurfaceFlags::kNone);
+        proxyColorTypes[0] = GrColorType::kRGBA_8888;
     }
     {
         GrSurfaceDesc dummyDesc;
@@ -289,6 +291,7 @@
                                                 kTopLeft_GrSurfaceOrigin, mipMapped,
                                                 SkBackingFit::kExact, SkBudgeted::kNo,
                                                 GrProtected::kNo, GrInternalSurfaceFlags::kNone);
+        proxyColorTypes[1] = GrColorType::kAlpha_8;
     }
 
     if (!proxies[0] || !proxies[1]) {
@@ -311,7 +314,8 @@
         }
 
         GrPaint paint;
-        GrProcessorTestData ptd(&random, context, renderTargetContext.get(), proxies);
+        GrProcessorTestData ptd(&random, context, renderTargetContext.get(), proxies,
+                                proxyColorTypes);
         set_random_color_coverage_stages(&paint, &ptd, maxStages, maxLevels);
         set_random_xpf(&paint, &ptd);
         GrDrawRandomOp(&random, renderTargetContext.get(), std::move(paint));
@@ -336,7 +340,8 @@
     for (int i = 0; i < fpFactoryCnt; ++i) {
         // Since FP factories internally randomize, call each 10 times.
         for (int j = 0; j < 10; ++j) {
-            GrProcessorTestData ptd(&random, context, renderTargetContext.get(), proxies);
+            GrProcessorTestData ptd(&random, context, renderTargetContext.get(), proxies,
+                                    proxyColorTypes);
 
             GrPaint paint;
             paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
diff --git a/tests/GrMipMappedTest.cpp b/tests/GrMipMappedTest.cpp
index fd47421..6bb6afd 100644
--- a/tests/GrMipMappedTest.cpp
+++ b/tests/GrMipMappedTest.cpp
@@ -350,9 +350,9 @@
             GrMipMapped::kNo, SkBackingFit::kApprox, SkBudgeted::kYes, GrProtected::kNo);
     auto rtc = drawingManager->makeRenderTargetContext(
             std::move(renderTarget), colorType, nullptr, nullptr, true);
-    rtc->drawTexture(GrNoClip(), mipmapProxy, filter, SkBlendMode::kSrcOver, {1,1,1,1},
-                     SkRect::MakeWH(4, 4), SkRect::MakeWH(1,1), GrAA::kYes, GrQuadAAFlags::kAll,
-                     SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(), nullptr);
+    rtc->drawTexture(GrNoClip(), mipmapProxy, colorType, filter, SkBlendMode::kSrcOver,
+                     {1,1,1,1}, SkRect::MakeWH(4, 4), SkRect::MakeWH(1,1), GrAA::kYes,
+                     GrQuadAAFlags::kAll, SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(), nullptr);
     return rtc;
 }
 
diff --git a/tests/GrSurfaceTest.cpp b/tests/GrSurfaceTest.cpp
index 363d2f6..be6114e 100644
--- a/tests/GrSurfaceTest.cpp
+++ b/tests/GrSurfaceTest.cpp
@@ -606,10 +606,11 @@
                         GrMipMapsStatus::kNotAllocated, GrInternalSurfaceFlags ::kNone,
                         SkBackingFit::kExact, budgeted, GrProtected::kNo,
                         GrSurfaceProxy::UseAllocator::kYes);
-                rtc->drawTexture(GrNoClip(), proxy, GrSamplerState::Filter::kNearest,
-                                 SkBlendMode::kSrcOver, SkPMColor4f(), SkRect::MakeWH(w, h),
-                                 SkRect::MakeWH(w, h), GrAA::kNo, GrQuadAAFlags::kNone,
-                                 SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(), nullptr);
+                rtc->drawTexture(GrNoClip(), proxy, GrColorType::kRGBA_8888,
+                                 GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver,
+                                 SkPMColor4f(), SkRect::MakeWH(w, h), SkRect::MakeWH(w, h),
+                                 GrAA::kNo, GrQuadAAFlags::kNone, SkCanvas::kFast_SrcRectConstraint,
+                                 SkMatrix::I(), nullptr);
                 // We still have the proxy, which should remain instantiated, thereby keeping the
                 // texture not purgeable.
                 REPORTER_ASSERT(reporter, idleIDs.find(2) == idleIDs.end());
@@ -619,10 +620,11 @@
                 REPORTER_ASSERT(reporter, idleIDs.find(2) == idleIDs.end());
 
                 // This time we move the proxy into the draw.
-                rtc->drawTexture(GrNoClip(), std::move(proxy), GrSamplerState::Filter::kNearest,
-                                 SkBlendMode::kSrcOver, SkPMColor4f(), SkRect::MakeWH(w, h),
-                                 SkRect::MakeWH(w, h), GrAA::kNo, GrQuadAAFlags::kNone,
-                                 SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(), nullptr);
+                rtc->drawTexture(GrNoClip(), std::move(proxy), GrColorType::kRGBA_8888,
+                                 GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver,
+                                 SkPMColor4f(), SkRect::MakeWH(w, h), SkRect::MakeWH(w, h),
+                                 GrAA::kNo, GrQuadAAFlags::kNone, SkCanvas::kFast_SrcRectConstraint,
+                                 SkMatrix::I(), nullptr);
                 REPORTER_ASSERT(reporter, idleIDs.find(2) == idleIDs.end());
                 context->flush();
                 context->priv().getGpu()->testingOnly_flushGpuAndSync();
@@ -665,9 +667,10 @@
                             auto proxy = context->priv().proxyProvider()->testingOnly_createWrapped(
                                     texture, GrColorType::kRGBA_8888, kTopLeft_GrSurfaceOrigin);
                             rtc->drawTexture(
-                                    GrNoClip(), proxy, GrSamplerState::Filter::kNearest,
-                                    SkBlendMode::kSrcOver, SkPMColor4f(), SkRect::MakeWH(w, h),
-                                    SkRect::MakeWH(w, h), GrAA::kNo, GrQuadAAFlags::kNone,
+                                    GrNoClip(), proxy, GrColorType::kRGBA_8888,
+                                    GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver,
+                                    SkPMColor4f(), SkRect::MakeWH(w, h), SkRect::MakeWH(w, h),
+                                    GrAA::kNo, GrQuadAAFlags::kNone,
                                     SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(), nullptr);
                             if (drawType == DrawType::kDrawAndFlush) {
                                 context->flush();
diff --git a/tests/OnFlushCallbackTest.cpp b/tests/OnFlushCallbackTest.cpp
index 5567532..9f0e4f0 100644
--- a/tests/OnFlushCallbackTest.cpp
+++ b/tests/OnFlushCallbackTest.cpp
@@ -431,7 +431,8 @@
 
 // This creates an off-screen rendertarget whose ops which eventually pull from the atlas.
 static sk_sp<GrTextureProxy> make_upstream_image(GrContext* context, AtlasObject* object, int start,
-                                                 sk_sp<GrTextureProxy> atlasProxy) {
+                                                 sk_sp<GrTextureProxy> atlasProxy,
+                                                 GrColorType atlasColorType) {
     auto rtc = context->priv().makeDeferredRenderTargetContext(SkBackingFit::kApprox,
                                                                3* kDrawnTileSize,
                                                                kDrawnTileSize,
@@ -443,7 +444,7 @@
     for (int i = 0; i < 3; ++i) {
         SkRect r = SkRect::MakeXYWH(i*kDrawnTileSize, 0, kDrawnTileSize, kDrawnTileSize);
 
-        auto fp = GrSimpleTextureEffect::Make(atlasProxy, SkMatrix::I());
+        auto fp = GrSimpleTextureEffect::Make(atlasProxy, atlasColorType, SkMatrix::I());
         GrPaint paint;
         paint.addColorFragmentProcessor(std::move(fp));
         paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
@@ -543,7 +544,8 @@
     for (int i = 0; i < kNumProxies; ++i) {
         proxies[i] = make_upstream_image(context, &object, i*3,
                                          object.getAtlasProxy(proxyProvider,
-                                                              context->priv().caps()));
+                                                              context->priv().caps()),
+                                         GrColorType::kRGBA_8888);
     }
 
     static const int kFinalWidth = 6*kDrawnTileSize;
@@ -561,7 +563,7 @@
         SkMatrix t = SkMatrix::MakeTrans(-i*3*kDrawnTileSize, 0);
 
         GrPaint paint;
-        auto fp = GrSimpleTextureEffect::Make(std::move(proxies[i]), t);
+        auto fp = GrSimpleTextureEffect::Make(std::move(proxies[i]), GrColorType::kRGBA_8888, t);
         paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
         paint.addColorFragmentProcessor(std::move(fp));
 
diff --git a/tests/ProcessorTest.cpp b/tests/ProcessorTest.cpp
index 0b0420b..6d74019 100644
--- a/tests/ProcessorTest.cpp
+++ b/tests/ProcessorTest.cpp
@@ -243,9 +243,10 @@
 void test_draw_op(GrContext* context,
                   GrRenderTargetContext* rtc,
                   std::unique_ptr<GrFragmentProcessor> fp,
-                  sk_sp<GrTextureProxy> inputDataProxy) {
+                  sk_sp<GrTextureProxy> inputDataProxy,
+                  GrColorType inputColorType) {
     GrPaint paint;
-    paint.addColorTextureProcessor(std::move(inputDataProxy), SkMatrix::I());
+    paint.addColorTextureProcessor(std::move(inputDataProxy), inputColorType, SkMatrix::I());
     paint.addColorFragmentProcessor(std::move(fp));
     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
@@ -256,12 +257,12 @@
 
 // This assumes that the output buffer will be the same size as inputDataProxy
 void render_fp(GrContext* context, GrRenderTargetContext* rtc, GrFragmentProcessor* fp,
-               sk_sp<GrTextureProxy> inputDataProxy, GrColor* buffer) {
+               sk_sp<GrTextureProxy> inputDataProxy, GrColorType inputColorType, GrColor* buffer) {
     int width = inputDataProxy->width();
     int height = inputDataProxy->height();
 
     // test_draw_op needs to take ownership of an FP, so give it a clone that it can own
-    test_draw_op(context, rtc, fp->clone(), inputDataProxy);
+    test_draw_op(context, rtc, fp->clone(), inputDataProxy, inputColorType);
     memset(buffer, 0x0, sizeof(GrColor) * width * height);
     rtc->readPixels(SkImageInfo::Make(width, height, kRGBA_8888_SkColorType, kPremul_SkAlphaType),
                     buffer, 0, {0, 0});
@@ -271,7 +272,8 @@
 bool init_test_textures(GrResourceProvider* resourceProvider,
                         GrProxyProvider* proxyProvider,
                         SkRandom* random,
-                        sk_sp<GrTextureProxy> proxies[2]) {
+                        sk_sp<GrTextureProxy> proxies[2],
+                        GrColorType proxyColorTypes[2]) {
     static const int kTestTextureSize = 256;
 
     {
@@ -291,6 +293,7 @@
         proxies[0] =
                 proxyProvider->createTextureProxy(img, 1, SkBudgeted::kYes, SkBackingFit::kExact);
         proxies[0]->instantiate(resourceProvider);
+        proxyColorTypes[0] = GrColorType::kRGBA_8888;
     }
 
     {
@@ -309,6 +312,7 @@
         proxies[1] =
                 proxyProvider->createTextureProxy(img, 1, SkBudgeted::kYes, SkBackingFit::kExact);
         proxies[1]->instantiate(resourceProvider);
+        proxyColorTypes[1] = GrColorType::kAlpha_8;
     }
 
     return proxies[0] && proxies[1];
@@ -443,11 +447,12 @@
             SkBackingFit::kExact, kRenderSize, kRenderSize, GrColorType::kRGBA_8888, nullptr);
 
     sk_sp<GrTextureProxy> proxies[2];
-    if (!init_test_textures(resourceProvider, proxyProvider, &random, proxies)) {
+    GrColorType proxyColorTypes[2];
+    if (!init_test_textures(resourceProvider, proxyProvider, &random, proxies, proxyColorTypes)) {
         ERRORF(reporter, "Could not create test textures");
         return;
     }
-    GrProcessorTestData testData(&random, context, rtc.get(), proxies);
+    GrProcessorTestData testData(&random, context, rtc.get(), proxies, proxyColorTypes);
 
     // Coverage optimization uses three frames with a linearly transformed input texture.  The first
     // frame has no offset, second frames add .2 and .4, which should then be present as a fixed
@@ -494,12 +499,15 @@
 
             if (fp->compatibleWithCoverageAsAlpha()) {
                 // 2nd and 3rd frames are only used when checking coverage optimization
-                render_fp(context, rtc.get(), fp.get(), inputTexture2, readData2.get());
-                render_fp(context, rtc.get(), fp.get(), inputTexture3, readData3.get());
+                render_fp(context, rtc.get(), fp.get(), inputTexture2, GrColorType::kRGBA_8888,
+                          readData2.get());
+                render_fp(context, rtc.get(), fp.get(), inputTexture3, GrColorType::kRGBA_8888,
+                          readData3.get());
             }
             // Draw base frame last so that rtc holds the original FP behavior if we need to
             // dump the image to the log.
-            render_fp(context, rtc.get(), fp.get(), inputTexture1, readData1.get());
+            render_fp(context, rtc.get(), fp.get(), inputTexture1, GrColorType::kRGBA_8888,
+                      readData1.get());
 
             if (0) {  // Useful to see what FPs are being tested.
                 SkString children;
@@ -677,11 +685,12 @@
             SkBackingFit::kExact, kRenderSize, kRenderSize, GrColorType::kRGBA_8888, nullptr);
 
     sk_sp<GrTextureProxy> proxies[2];
-    if (!init_test_textures(resourceProvider, proxyProvider, &random, proxies)) {
+    GrColorType proxyColorTypes[2];
+    if (!init_test_textures(resourceProvider, proxyProvider, &random, proxies, proxyColorTypes)) {
         ERRORF(reporter, "Could not create test textures");
         return;
     }
-    GrProcessorTestData testData(&random, context, rtc.get(), proxies);
+    GrProcessorTestData testData(&random, context, rtc.get(), proxies, proxyColorTypes);
 
     auto inputTexture = make_input_texture(proxyProvider, kRenderSize, kRenderSize, 0.0f);
     std::unique_ptr<GrColor[]> readData1(new GrColor[kRenderSize * kRenderSize]);
@@ -721,10 +730,12 @@
             REPORTER_ASSERT(reporter, fp->numChildProcessors() == clone->numChildProcessors());
             REPORTER_ASSERT(reporter, fp->usesLocalCoords() == clone->usesLocalCoords());
             // Draw with original and read back the results.
-            render_fp(context, rtc.get(), fp.get(), inputTexture, readData1.get());
+            render_fp(context, rtc.get(), fp.get(), inputTexture, GrColorType::kRGBA_8888,
+                      readData1.get());
 
             // Draw with clone and read back the results.
-            render_fp(context, rtc.get(), clone.get(), inputTexture, readData2.get());
+            render_fp(context, rtc.get(), clone.get(), inputTexture, GrColorType::kRGBA_8888,
+                      readData2.get());
 
             // Check that the results are the same.
             bool passing = true;
diff --git a/tests/RectangleTextureTest.cpp b/tests/RectangleTextureTest.cpp
index 9d10b1f..16afbcf 100644
--- a/tests/RectangleTextureTest.cpp
+++ b/tests/RectangleTextureTest.cpp
@@ -33,7 +33,7 @@
                         GrSamplerState::Filter::kMipMap}) {
         rtContext->clear(nullptr, SkPMColor4f::FromBytes_RGBA(0xDDCCBBAA),
                          GrRenderTargetContext::CanClearFullscreen::kYes);
-        auto fp = GrSimpleTextureEffect::Make(rectProxy, SkMatrix::I(), filter);
+        auto fp = GrSimpleTextureEffect::Make(rectProxy, colorType, SkMatrix::I(), filter);
         GrPaint paint;
         paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
         paint.addColorFragmentProcessor(std::move(fp));
diff --git a/tests/TestUtils.cpp b/tests/TestUtils.cpp
index 2e6120a..d9f05b1 100644
--- a/tests/TestUtils.cpp
+++ b/tests/TestUtils.cpp
@@ -76,8 +76,9 @@
 void test_copy_from_surface(skiatest::Reporter* reporter, GrContext* context, GrSurfaceProxy* proxy,
                             GrColorType colorType, uint32_t expectedPixelValues[],
                             const char* testName) {
-    sk_sp<GrTextureProxy> dstProxy = GrSurfaceProxy::Copy(context, proxy, GrMipMapped::kNo,
-                                                          SkBackingFit::kExact, SkBudgeted::kYes);
+    sk_sp<GrTextureProxy> dstProxy = GrSurfaceProxy::Copy(context, proxy, colorType,
+                                                          GrMipMapped::kNo, SkBackingFit::kExact,
+                                                          SkBudgeted::kYes);
     SkASSERT(dstProxy);
 
     auto dstContext = context->priv().makeWrappedSurfaceContext(std::move(dstProxy), colorType,