Better handle colorTypes in GrTexutreProducer.

This change does a bunch of stuff that all sadly needs to land together.

First this moves the fallback for bitmap upload from proxyprovider to
GrBitmapTextureMaker. This is mostly a code organization cleanup but also
allows us to manager all colorType changes in the GrTextureProducers
directly.

Next this change hides colorType and deletes colorInfo getters from
public. Looking at the colorType of the producer doesn't really make
sense (outside the producer) since we have multiple fallbacks that
could happen in terms of format for the produced textures.

Next this makes sure that after the ctor is called, the internal
colorType stored will always be the used colorType by returned textures.
The only caveat to this is if a texture needs a copy for repeat mode
and we end up needing to render to fallback configs. Modulo repeat issue
the only other thing to change colorType is uploading a CPU bitmap if
we fallback to 8888, but this can be known in the ctor if this will
happen.

Finally, the only users of GrTextureProducer that really need to know
the correct colorType to use with the returned texture are those that
are then creating an Image. However, non of these cases even need to
pass in sampling params so we don't hit the need for repeat copies
and thus colorType changes. So now the refTextureProxy call (the one
without params) returns a pair of the proxy and colorType. The producer
just returns its colorType cause nothing could have changed that.

Bug: skia:6718
Change-Id: Ic5b5810606440ff943910933a3880d62875c9c16
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/264836
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
diff --git a/src/gpu/GrBitmapTextureMaker.cpp b/src/gpu/GrBitmapTextureMaker.cpp
index c2fcce9..129f06e 100644
--- a/src/gpu/GrBitmapTextureMaker.cpp
+++ b/src/gpu/GrBitmapTextureMaker.cpp
@@ -17,10 +17,20 @@
 #include "src/gpu/GrSurfaceContext.h"
 #include "src/gpu/SkGr.h"
 
+static GrImageInfo get_image_info(GrRecordingContext* context, const SkBitmap& bitmap) {
+    GrColorType ct = SkColorTypeToGrColorType(bitmap.info().colorType());
+    GrBackendFormat format = context->priv().caps()->getDefaultBackendFormat(ct, GrRenderable::kNo);
+    if (!format.isValid()) {
+        ct = GrColorType::kRGBA_8888;
+    }
+    return {ct, bitmap.alphaType(), bitmap.refColorSpace(), bitmap.dimensions()};
+}
+
 GrBitmapTextureMaker::GrBitmapTextureMaker(GrRecordingContext* context, const SkBitmap& bitmap,
-                                           bool useDecal)
-        : INHERITED(context, bitmap.info(), useDecal), fBitmap(bitmap) {
-    if (!bitmap.isVolatile()) {
+                                           bool useDecal, bool shouldUseUniqueKey)
+        : INHERITED(context, get_image_info(context, bitmap), useDecal)
+        , fBitmap(bitmap) {
+    if (!bitmap.isVolatile() && shouldUseUniqueKey) {
         SkIPoint origin = bitmap.pixelRefOrigin();
         SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, bitmap.width(),
                                            bitmap.height());
@@ -47,8 +57,20 @@
     }
 
     if (!proxy) {
-        proxy = proxyProvider->createProxyFromBitmap(fBitmap, willBeMipped ? GrMipMapped::kYes
-                                                                           : GrMipMapped::kNo);
+        if (this->colorType() != SkColorTypeToGrColorType(fBitmap.info().colorType())) {
+            SkASSERT(this->colorType() == GrColorType::kRGBA_8888);
+            SkBitmap copy8888;
+            if (!copy8888.tryAllocPixels(fBitmap.info().makeColorType(kRGBA_8888_SkColorType)) ||
+                !fBitmap.readPixels(copy8888.pixmap())) {
+                return nullptr;
+            }
+            copy8888.setImmutable();
+            proxy = proxyProvider->createProxyFromBitmap(copy8888, willBeMipped ? GrMipMapped::kYes
+                                                                                : GrMipMapped::kNo);
+        } else {
+            proxy = proxyProvider->createProxyFromBitmap(fBitmap, willBeMipped ? GrMipMapped::kYes
+                                                                               : GrMipMapped::kNo);
+        }
         if (proxy) {
             if (fOriginalKey.isValid()) {
                 proxyProvider->assignUniqueKeyToProxy(fOriginalKey, proxy.get());
diff --git a/src/gpu/GrBitmapTextureMaker.h b/src/gpu/GrBitmapTextureMaker.h
index 9205b90..984cd40 100644
--- a/src/gpu/GrBitmapTextureMaker.h
+++ b/src/gpu/GrBitmapTextureMaker.h
@@ -17,16 +17,15 @@
 class GrBitmapTextureMaker : public GrTextureMaker {
 public:
     GrBitmapTextureMaker(GrRecordingContext* context, const SkBitmap& bitmap,
-                         bool useDecal = false);
+                         bool useDecal = false, bool shouldUseUniqueKey = true);
 
-protected:
+private:
     sk_sp<GrTextureProxy> refOriginalTextureProxy(bool willBeMipped,
                                                   AllowedTexGenType onlyIfFast) override;
 
     void makeCopyKey(const CopyParams& copyParams, GrUniqueKey* copyKey) override;
     void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) override;
 
-private:
     const SkBitmap  fBitmap;
     GrUniqueKey     fOriginalKey;
 
diff --git a/src/gpu/GrImageTextureMaker.cpp b/src/gpu/GrImageTextureMaker.cpp
index 39bde1a..ead5dfe 100644
--- a/src/gpu/GrImageTextureMaker.cpp
+++ b/src/gpu/GrImageTextureMaker.cpp
@@ -8,14 +8,24 @@
 #include "src/gpu/GrImageTextureMaker.h"
 
 #include "src/gpu/GrColorSpaceXform.h"
+#include "src/gpu/GrRecordingContextPriv.h"
 #include "src/gpu/SkGr.h"
 #include "src/gpu/effects/GrYUVtoRGBEffect.h"
 #include "src/image/SkImage_GpuYUVA.h"
 #include "src/image/SkImage_Lazy.h"
 
+static GrImageInfo get_image_info(GrRecordingContext* context, const SkImage* client) {
+    SkASSERT(client->isLazyGenerated());
+    const SkImage_Lazy* lazyImage = static_cast<const SkImage_Lazy*>(client);
+
+    GrColorType ct = lazyImage->colorTypeOfLockTextureProxy(context->priv().caps());
+
+    return {ct, client->alphaType(), client->refColorSpace(), client->dimensions()};
+}
+
 GrImageTextureMaker::GrImageTextureMaker(GrRecordingContext* context, const SkImage* client,
                                          SkImage::CachingHint chint, bool useDecal)
-        : INHERITED(context, client->imageInfo(), useDecal)
+        : INHERITED(context, get_image_info(context, client), useDecal)
         , fImage(static_cast<const SkImage_Lazy*>(client))
         , fCachingHint(chint) {
     SkASSERT(client->isLazyGenerated());
diff --git a/src/gpu/GrImageTextureMaker.h b/src/gpu/GrImageTextureMaker.h
index 44e7424..c49e106 100644
--- a/src/gpu/GrImageTextureMaker.h
+++ b/src/gpu/GrImageTextureMaker.h
@@ -21,7 +21,7 @@
     GrImageTextureMaker(GrRecordingContext* context, const SkImage* client,
                         SkImage::CachingHint chint, bool useDecal = false);
 
-protected:
+private:
     // TODO: consider overriding this, for the case where the underlying generator might be
     //       able to efficiently produce a "stretched" texture natively (e.g. picture-backed)
     //          GrTexture* generateTextureForParams(const CopyParams&) override;
@@ -31,7 +31,6 @@
     void makeCopyKey(const CopyParams& stretch, GrUniqueKey* paramsCopyKey) override;
     void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) override {}
 
-private:
     const SkImage_Lazy*     fImage;
     GrUniqueKey             fOriginalKey;
     SkImage::CachingHint    fCachingHint;
diff --git a/src/gpu/GrProxyProvider.cpp b/src/gpu/GrProxyProvider.cpp
index 172afdd..34e2947 100644
--- a/src/gpu/GrProxyProvider.cpp
+++ b/src/gpu/GrProxyProvider.cpp
@@ -369,18 +369,7 @@
     GrBackendFormat format = this->caps()->getDefaultBackendFormat(
             SkColorTypeToGrColorType(bitmap.info().colorType()), GrRenderable::kNo);
     if (!format.isValid()) {
-        SkBitmap copy8888;
-        if (!copy8888.tryAllocPixels(bitmap.info().makeColorType(kRGBA_8888_SkColorType)) ||
-            !bitmap.readPixels(copy8888.pixmap())) {
-            return nullptr;
-        }
-        copy8888.setImmutable();
-        baseLevel = SkMakeImageFromRasterBitmap(copy8888, kNever_SkCopyPixelsMode);
-        desc.fConfig = kRGBA_8888_GrPixelConfig;
-        format = this->caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888, GrRenderable::kNo);
-        if (!format.isValid()) {
-            return nullptr;
-        }
+        return nullptr;
     }
 
     SkPixmap pixmap;
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 640feb0..6c9ef47 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -1654,7 +1654,7 @@
                                              GrPaint&& paint,
                                              const SkMatrix& viewMatrix,
                                              GrSurfaceProxyView view,
-                                             GrColorType srcColorType,
+                                             SkAlphaType alphaType,
                                              sk_sp<GrColorSpaceXform> csxf,
                                              GrSamplerState::Filter filter,
                                              std::unique_ptr<SkLatticeIter> iter,
@@ -1668,7 +1668,7 @@
 
     std::unique_ptr<GrDrawOp> op =
             GrLatticeOp::MakeNonAA(fContext, std::move(paint), viewMatrix, std::move(view),
-                                   srcColorType, std::move(csxf), filter, std::move(iter), dst);
+                                   alphaType, std::move(csxf), filter, std::move(iter), dst);
     this->addDrawOp(clip, std::move(op));
 }
 
diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h
index fd9ebe9..eda8654 100644
--- a/src/gpu/GrRenderTargetContext.h
+++ b/src/gpu/GrRenderTargetContext.h
@@ -489,7 +489,7 @@
                           GrPaint&&,
                           const SkMatrix& viewMatrix,
                           GrSurfaceProxyView,
-                          GrColorType srcColorType,
+                          SkAlphaType alphaType,
                           sk_sp<GrColorSpaceXform>,
                           GrSamplerState::Filter,
                           std::unique_ptr<SkLatticeIter>,
diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp
index a96e744..1f6b398 100644
--- a/src/gpu/GrSurfaceProxy.cpp
+++ b/src/gpu/GrSurfaceProxy.cpp
@@ -274,6 +274,10 @@
            fDimensions == GrResourceProvider::MakeApprox(fDimensions);
 }
 
+bool GrSurfaceProxy::isFormatCompressed(const GrCaps* caps) const {
+    return caps->isFormatCompressed(this->backendFormat());
+}
+
 #ifdef SK_DEBUG
 void GrSurfaceProxy::validate(GrContext_Base* context) const {
     if (fTarget) {
diff --git a/src/gpu/GrSurfaceProxy.h b/src/gpu/GrSurfaceProxy.h
index be63885..15888a6 100644
--- a/src/gpu/GrSurfaceProxy.h
+++ b/src/gpu/GrSurfaceProxy.h
@@ -143,6 +143,8 @@
 
     const GrBackendFormat& backendFormat() const { return fFormat; }
 
+    bool isFormatCompressed(const GrCaps*) const;
+
     class UniqueID {
     public:
         static UniqueID InvalidID() {
diff --git a/src/gpu/GrTextureProducer.cpp b/src/gpu/GrTextureProducer.cpp
index 29d4f38..46c6134 100644
--- a/src/gpu/GrTextureProducer.cpp
+++ b/src/gpu/GrTextureProducer.cpp
@@ -256,47 +256,45 @@
                                                                   SkScalar scaleAdjust[2]) {
     // Check that the caller pre-initialized scaleAdjust
     SkASSERT(!scaleAdjust || (scaleAdjust[0] == 1 && scaleAdjust[1] == 1));
-    // Check that if the caller passed nullptr for scaleAdjust that we're in the case where there
-    // can be no scaling.
-    SkDEBUGCODE(bool expectNoScale = (sampler.filter() != GrSamplerState::Filter::kMipMap &&
-                                      !sampler.isRepeated()));
-    SkASSERT(scaleAdjust || expectNoScale);
+
+    const GrCaps* caps = this->context()->priv().caps();
 
     int mipCount = SkMipMap::ComputeLevelCount(this->width(), this->height());
     bool willBeMipped = GrSamplerState::Filter::kMipMap == sampler.filter() && mipCount &&
-                        this->context()->priv().caps()->mipMapSupport();
+                        caps->mipMapSupport();
 
     auto result = this->onRefTextureProxyForParams(sampler, willBeMipped, scaleAdjust);
 
     // Check to make sure that if we say the texture willBeMipped that the returned texture has mip
     // maps, unless the config is not copyable.
     SkASSERT(!result || !willBeMipped || result->mipMapped() == GrMipMapped::kYes ||
-             !this->context()->priv().caps()->isFormatCopyable(result->backendFormat()));
+             !caps->isFormatCopyable(result->backendFormat()));
 
+    SkDEBUGCODE(bool expectNoScale = (sampler.filter() != GrSamplerState::Filter::kMipMap &&
+                                      !sampler.isRepeated()));
     // Check that the "no scaling expected" case always returns a proxy of the same size as the
     // producer.
     SkASSERT(!result || !expectNoScale || result->dimensions() == this->dimensions());
+
     return result;
 }
 
-sk_sp<GrTextureProxy> GrTextureProducer::refTextureProxy(GrMipMapped willNeedMips) {
+std::pair<sk_sp<GrTextureProxy>, GrColorType> GrTextureProducer::refTextureProxy(
+        GrMipMapped willNeedMips) {
     GrSamplerState::Filter filter =
             GrMipMapped::kNo == willNeedMips ? GrSamplerState::Filter::kNearest
                                              : GrSamplerState::Filter::kMipMap;
     GrSamplerState sampler(GrSamplerState::WrapMode::kClamp, filter);
 
-    int mipCount = SkMipMap::ComputeLevelCount(this->width(), this->height());
-    bool willBeMipped = GrSamplerState::Filter::kMipMap == sampler.filter() && mipCount &&
-                        this->context()->priv().caps()->mipMapSupport();
+    auto result = this->refTextureProxyForParams(sampler, nullptr);
 
-    auto result = this->onRefTextureProxyForParams(sampler, willBeMipped, nullptr);
+#ifdef SK_DEBUG
+    const GrCaps* caps = this->context()->priv().caps();
+    // Check that the resulting proxy format is compatible with the GrColorType of this producer
+    SkASSERT(!result ||
+             result->isFormatCompressed(caps) ||
+             caps->areColorTypeAndFormatCompatible(this->colorType(), result->backendFormat()));
+#endif
 
-    // Check to make sure that if we say the texture willBeMipped that the returned texture has mip
-    // maps, unless the config is not copyable.
-    SkASSERT(!result || !willBeMipped || result->mipMapped() == GrMipMapped::kYes ||
-             !this->context()->priv().caps()->isFormatCopyable(result->backendFormat()));
-
-    // Check that no scaling occured and we returned a proxy of the same size as the producer.
-    SkASSERT(!result || result->dimensions() == this->dimensions());
-    return result;
+    return {result, this->colorType()};
 }
diff --git a/src/gpu/GrTextureProducer.h b/src/gpu/GrTextureProducer.h
index 239b257..a75380a 100644
--- a/src/gpu/GrTextureProducer.h
+++ b/src/gpu/GrTextureProducer.h
@@ -96,15 +96,13 @@
     // wrap mode. To support that flag now would require us to support scaleAdjust array like in
     // refTextureProxyForParams, however the current public API that uses this call does not expose
     // that array.
-    sk_sp<GrTextureProxy> refTextureProxy(GrMipMapped willNeedMips);
+    std::pair<sk_sp<GrTextureProxy>, GrColorType> refTextureProxy(GrMipMapped willNeedMips);
 
     virtual ~GrTextureProducer() {}
 
     int width() const { return fImageInfo.width(); }
     int height() const { return fImageInfo.height(); }
     SkISize dimensions() const { return fImageInfo.dimensions(); }
-    const GrColorInfo& colorInfo() const { return fImageInfo.colorInfo(); }
-    GrColorType colorType() const { return fImageInfo.colorType(); }
     SkAlphaType alphaType() const { return fImageInfo.alphaType(); }
     SkColorSpace* colorSpace() const { return fImageInfo.colorSpace(); }
     bool isAlphaOnly() const { return GrColorTypeIsAlphaOnly(fImageInfo.colorType()); }
@@ -120,6 +118,8 @@
                       bool domainNeedsDecal)
             : fContext(context), fImageInfo(imageInfo), fDomainNeedsDecal(domainNeedsDecal) {}
 
+    GrColorType colorType() const { return fImageInfo.colorType(); }
+
     /** Helper for creating a key for a copy from an original key. */
     static void MakeCopyKeyFromOrigKey(const GrUniqueKey& origKey,
                                        const CopyParams& copyParams,
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index a8c1966..6fa5173 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1371,7 +1371,7 @@
     GrSurfaceProxyView view(std::move(proxy), origin, swizzle);
 
     fRenderTargetContext->drawImageLattice(this->clip(), std::move(grPaint), this->localToDevice(),
-                                           std::move(view), producer->colorType(), std::move(csxf),
+                                           std::move(view), producer->alphaType(), std::move(csxf),
                                            filter, std::move(iter), dst);
 }
 
diff --git a/src/gpu/SkGpuDevice_drawTexture.cpp b/src/gpu/SkGpuDevice_drawTexture.cpp
index 241b857..6d5d0f0 100644
--- a/src/gpu/SkGpuDevice_drawTexture.cpp
+++ b/src/gpu/SkGpuDevice_drawTexture.cpp
@@ -241,13 +241,14 @@
     if (attemptDrawTexture && can_use_draw_texture(paint)) {
         // We've done enough checks above to allow us to pass ClampNearest() and not check for
         // scaling adjustments.
-        auto proxy = producer->refTextureProxyForParams(GrSamplerState::Filter::kNearest, nullptr);
+        auto [proxy, ct] = producer->refTextureProxy(GrMipMapped::kNo);
         if (!proxy) {
             return;
         }
 
         draw_texture(rtc, clip, ctm, paint, src, dst, dstClip, aa, aaFlags, constraint,
-                     std::move(proxy), producer->colorInfo());
+                     std::move(proxy),
+                     {ct, producer->alphaType(), sk_ref_sp(producer->colorSpace())});
         return;
     }
 
@@ -403,7 +404,14 @@
         SK_HISTOGRAM_BOOLEAN("DrawTiled", false);
         LogDrawScaleFactor(ctm, srcToDst, paint.getFilterQuality());
 
-        GrColorInfo colorInfo(image->imageInfo().colorInfo());
+        GrColorInfo colorInfo;
+        if (fContext->priv().caps()->isFormatSRGB(proxy->backendFormat())) {
+            SkASSERT(image->imageInfo().colorType() == kRGBA_8888_SkColorType);
+            colorInfo = GrColorInfo(GrColorType::kRGBA_8888_SRGB, image->imageInfo().alphaType(),
+                                    image->imageInfo().refColorSpace());
+        } else {
+            colorInfo = GrColorInfo(image->imageInfo().colorInfo());
+        }
 
         if (attemptDrawTexture && can_use_draw_texture(paint)) {
             draw_texture(fRenderTargetContext.get(), this->clip(), ctm, paint, src,  dst,
diff --git a/src/gpu/effects/GrRectBlurEffect.fp b/src/gpu/effects/GrRectBlurEffect.fp
index 73fd214..8cf364b 100644
--- a/src/gpu/effects/GrRectBlurEffect.fp
+++ b/src/gpu/effects/GrRectBlurEffect.fp
@@ -75,6 +75,9 @@
         }
         *bitmap.getAddr8(width - 1, 0) = 0;
         bitmap.setImmutable();
+        // We directly call the proxyProvider instead of going through GrBitmapTextureMaker. This
+        // means we won't fall back to RGBA_8888. But we should have support for a single channel
+        // unorm format so we shouldn't need the fallback.
         proxy = proxyProvider->createProxyFromBitmap(bitmap, GrMipMapped::kNo);
         if (!proxy) {
             return nullptr;
diff --git a/src/gpu/effects/generated/GrRectBlurEffect.h b/src/gpu/effects/generated/GrRectBlurEffect.h
index aa8c8a7..e454719 100644
--- a/src/gpu/effects/generated/GrRectBlurEffect.h
+++ b/src/gpu/effects/generated/GrRectBlurEffect.h
@@ -57,6 +57,9 @@
             }
             *bitmap.getAddr8(width - 1, 0) = 0;
             bitmap.setImmutable();
+            // We directly call the proxyProvider instead of going through GrBitmapTextureMaker.
+            // This means we won't fall back to RGBA_8888. But we should have support for a single
+            // channel unorm format so we shouldn't need the fallback.
             proxy = proxyProvider->createProxyFromBitmap(bitmap, GrMipMapped::kNo);
             if (!proxy) {
                 return nullptr;
diff --git a/src/gpu/ops/GrLatticeOp.cpp b/src/gpu/ops/GrLatticeOp.cpp
index 7bad753..9d84a5b 100644
--- a/src/gpu/ops/GrLatticeOp.cpp
+++ b/src/gpu/ops/GrLatticeOp.cpp
@@ -133,27 +133,27 @@
                                           GrPaint&& paint,
                                           const SkMatrix& viewMatrix,
                                           GrSurfaceProxyView view,
-                                          GrColorType srcColorType,
+                                          SkAlphaType alphaType,
                                           sk_sp<GrColorSpaceXform> colorSpaceXForm,
                                           GrSamplerState::Filter filter,
                                           std::unique_ptr<SkLatticeIter> iter,
                                           const SkRect& dst) {
         SkASSERT(view.proxy());
         return Helper::FactoryHelper<NonAALatticeOp>(context, std::move(paint), viewMatrix,
-                                                     std::move(view), srcColorType,
+                                                     std::move(view), alphaType,
                                                      std::move(colorSpaceXForm), filter,
                                                      std::move(iter), dst);
     }
 
     NonAALatticeOp(Helper::MakeArgs& helperArgs, const SkPMColor4f& color,
                    const SkMatrix& viewMatrix, GrSurfaceProxyView view,
-                   GrColorType srcColorType, sk_sp<GrColorSpaceXform> colorSpaceXform,
+                   SkAlphaType alphaType, sk_sp<GrColorSpaceXform> colorSpaceXform,
                    GrSamplerState::Filter filter, std::unique_ptr<SkLatticeIter> iter,
                    const SkRect& dst)
             : INHERITED(ClassID())
             , fHelper(helperArgs, GrAAType::kNone)
             , fView(std::move(view))
-            , fSrcColorType(srcColorType)
+            , fAlphaType(alphaType)
             , fColorSpaceXform(std::move(colorSpaceXform))
             , fFilter(filter) {
         Patch& patch = fPatches.push_back();
@@ -195,7 +195,7 @@
     GrProcessorSet::Analysis finalize(
             const GrCaps& caps, const GrAppliedClip* clip, bool hasMixedSampledCoverage,
             GrClampType clampType) override {
-        auto opaque = fPatches[0].fColor.isOpaque() && !GrColorTypeHasAlpha(fSrcColorType)
+        auto opaque = fPatches[0].fColor.isOpaque() && fAlphaType == kOpaque_SkAlphaType
                               ? GrProcessorAnalysisColor::Opaque::kYes
                               : GrProcessorAnalysisColor::Opaque::kNo;
         auto analysisColor = GrProcessorAnalysisColor(opaque);
@@ -328,7 +328,7 @@
     Helper fHelper;
     SkSTArray<1, Patch, true> fPatches;
     GrSurfaceProxyView fView;
-    GrColorType fSrcColorType;
+    SkAlphaType fAlphaType;
     sk_sp<GrColorSpaceXform> fColorSpaceXform;
     GrSamplerState::Filter fFilter;
     bool fWideColor;
@@ -343,14 +343,13 @@
                                     GrPaint&& paint,
                                     const SkMatrix& viewMatrix,
                                     GrSurfaceProxyView view,
-                                    GrColorType srcColorType,
+                                    SkAlphaType alphaType,
                                     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(view),
-                                srcColorType, std::move(colorSpaceXform), filter, std::move(iter),
-                                dst);
+    return NonAALatticeOp::Make(context, std::move(paint), viewMatrix, std::move(view), alphaType,
+                                std::move(colorSpaceXform), filter, std::move(iter), dst);
 }
 };
 
@@ -474,8 +473,7 @@
             context->priv().caps()->getReadSwizzle(format, GrColorType::kRGBA_8888));
 
     return NonAALatticeOp::Make(context, std::move(paint), viewMatrix, std::move(view),
-                                GrColorType::kRGBA_8888, std::move(csxf), filter, std::move(iter),
-                                dst);
+                                kPremul_SkAlphaType, std::move(csxf), filter, std::move(iter), dst);
 }
 
 #endif
diff --git a/src/gpu/ops/GrLatticeOp.h b/src/gpu/ops/GrLatticeOp.h
index a3851f9..d8c3de4 100644
--- a/src/gpu/ops/GrLatticeOp.h
+++ b/src/gpu/ops/GrLatticeOp.h
@@ -26,7 +26,7 @@
                                     GrPaint&&,
                                     const SkMatrix& viewMatrix,
                                     GrSurfaceProxyView view,
-                                    GrColorType srcColorType,
+                                    SkAlphaType alphaType,
                                     sk_sp<GrColorSpaceXform>,
                                     GrSamplerState::Filter,
                                     std::unique_ptr<SkLatticeIter>,
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index 8ce4209..6d2a48f 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -391,7 +391,7 @@
                                                  SkAlphaType at, uint32_t id,
                                                  GrMipMapped mipMapped) {
     // TODO: have texture producer return a GrSurfaceProxyView
-    sk_sp<GrTextureProxy> proxy(producer->refTextureProxy(mipMapped));
+    auto [proxy, colorType] = producer->refTextureProxy(mipMapped);
     if (!proxy) {
         return nullptr;
     }
@@ -531,12 +531,12 @@
         }
         pixmap = &resized;
     }
-    GrProxyProvider* proxyProvider = context->priv().proxyProvider();
     // Turn the pixmap into a GrTextureProxy
     SkBitmap bmp;
     bmp.installPixels(*pixmap);
+    GrBitmapTextureMaker bitmapMaker(context, bmp, false, false);
     GrMipMapped mipMapped = buildMips ? GrMipMapped::kYes : GrMipMapped::kNo;
-    sk_sp<GrTextureProxy> proxy = proxyProvider->createProxyFromBitmap(bmp, mipMapped);
+    auto [proxy, grCT] = bitmapMaker.refTextureProxy(mipMapped);
     if (!proxy) {
         return SkImage::MakeRasterCopy(*pixmap);
     }
@@ -549,8 +549,9 @@
 
     std::unique_ptr<GrSemaphore> sema = gpu->prepareTextureForCrossContextUsage(texture.get());
 
+    SkColorType skCT = GrColorTypeToSkColorType(grCT);
     auto gen = GrBackendTextureImageGenerator::Make(std::move(texture), proxy->origin(),
-                                                    std::move(sema), pixmap->colorType(),
+                                                    std::move(sema), skCT,
                                                     pixmap->alphaType(),
                                                     pixmap->info().refColorSpace());
     return SkImage::MakeFromGenerator(std::move(gen));
diff --git a/src/image/SkImage_GpuYUVA.cpp b/src/image/SkImage_GpuYUVA.cpp
index f134477..2c22053 100644
--- a/src/image/SkImage_GpuYUVA.cpp
+++ b/src/image/SkImage_GpuYUVA.cpp
@@ -16,6 +16,7 @@
 #include "src/core/SkAutoPixmapStorage.h"
 #include "src/core/SkMipMap.h"
 #include "src/core/SkScopeExit.h"
+#include "src/gpu/GrBitmapTextureMaker.h"
 #include "src/gpu/GrClip.h"
 #include "src/gpu/GrContextPriv.h"
 #include "src/gpu/GrGpu.h"
@@ -272,7 +273,6 @@
     }
 
     // Make proxies
-    GrProxyProvider* proxyProvider = context->priv().proxyProvider();
     sk_sp<GrTextureProxy> tempTextureProxies[4];
     GrColorType proxyColorTypes[4];
     for (int i = 0; i < numPixmaps; ++i) {
@@ -296,12 +296,13 @@
         // Turn the pixmap into a GrTextureProxy
         SkBitmap bmp;
         bmp.installPixels(*pixmap);
+        GrBitmapTextureMaker bitmapMaker(context, bmp, false, false);
         GrMipMapped mipMapped = buildMips ? GrMipMapped::kYes : GrMipMapped::kNo;
-        tempTextureProxies[i] = proxyProvider->createProxyFromBitmap(bmp, mipMapped);
+        std::tie(tempTextureProxies[i], proxyColorTypes[i]) =
+                bitmapMaker.refTextureProxy(mipMapped);
         if (!tempTextureProxies[i]) {
             return nullptr;
         }
-        proxyColorTypes[i] = SkColorTypeToGrColorType(bmp.colorType());
     }
 
     return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(context), imageSize, kNeedNewImageUniqueID,
diff --git a/src/image/SkImage_Lazy.cpp b/src/image/SkImage_Lazy.cpp
index f77ae8b..c47a9a5 100644
--- a/src/image/SkImage_Lazy.cpp
+++ b/src/image/SkImage_Lazy.cpp
@@ -18,6 +18,7 @@
 #if SK_SUPPORT_GPU
 #include "include/private/GrRecordingContext.h"
 #include "include/private/GrResourceKey.h"
+#include "src/gpu/GrBitmapTextureMaker.h"
 #include "src/gpu/GrCaps.h"
 #include "src/gpu/GrGpuResourcePriv.h"
 #include "src/gpu/GrImageTextureMaker.h"
@@ -518,8 +519,10 @@
     // 4. Ask the generator to return RGB(A) data, which the GPU can convert
     SkBitmap bitmap;
     if (!proxy && this->getROPixels(&bitmap, chint)) {
-        proxy = proxyProvider->createProxyFromBitmap(bitmap, willBeMipped ? GrMipMapped::kYes
-                                                                          : GrMipMapped::kNo);
+        GrBitmapTextureMaker bitmapMaker(ctx, bitmap, false, false);
+        GrColorType grCT;
+        std::tie(proxy, grCT) = bitmapMaker.refTextureProxy(willBeMipped ? GrMipMapped::kYes
+                                                                         : GrMipMapped::kNo);
         if (proxy && (!willBeMipped || GrMipMapped::kYes == proxy->mipMapped())) {
             SK_HISTOGRAM_ENUMERATION("LockTexturePath", kRGBA_LockTexturePath,
                                      kLockTexturePathCount);
@@ -555,6 +558,15 @@
     return nullptr;
 }
 
+GrColorType SkImage_Lazy::colorTypeOfLockTextureProxy(const GrCaps* caps) const {
+    GrColorType ct = SkColorTypeToGrColorType(this->colorType());
+    GrBackendFormat format = caps->getDefaultBackendFormat(ct, GrRenderable::kNo);
+    if (!format.isValid()) {
+        ct = GrColorType::kRGBA_8888;
+    }
+    return ct;
+}
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 sk_sp<SkImage> SkImage::DecodeToTexture(GrContext* ctx, const void* encoded, size_t length,
diff --git a/src/image/SkImage_Lazy.h b/src/image/SkImage_Lazy.h
index 0e40c4f..42d0f94 100644
--- a/src/image/SkImage_Lazy.h
+++ b/src/image/SkImage_Lazy.h
@@ -68,6 +68,12 @@
                                            bool willBeMipped,
                                            GrTextureMaker::AllowedTexGenType genType) const;
 
+    // Returns the GrColorType to use with the GrTextureProxy returned from lockTextureProxy. This
+    // may be different from the color type on the image in the case where we need up upload CPU
+    // data to a texture but the GPU doesn't support the format of CPU data. In this case we convert
+    // the data to RGBA_8888 unorm on the CPU then upload that.
+    GrColorType colorTypeOfLockTextureProxy(const GrCaps* caps) const;
+
     void makeCacheKeyFromOrigKey(const GrUniqueKey& origKey, GrUniqueKey* cacheKey) const;
 #endif