Reland "Don't flatten images in SkImageShader"

This is a reland of 318afe66e699970ebf789718b5a2297f783ed712

Original change's description:
> Don't flatten images in SkImageShader
> 
> Bug: skia:9570
> 
> Change-Id: Idd4485b5c5814501fe98fbf2115d89a80a41f5c7
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/299139
> Commit-Queue: Brian Salomon <bsalomon@google.com>
> Reviewed-by: Michael Ludwig <michaelludwig@google.com>

Bug: skia:9570
Change-Id: I4761e354dd4ec4f4a60097e06c3b9b9b73e538f6
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/299681
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/gpu/GrImageTextureMaker.cpp b/src/gpu/GrImageTextureMaker.cpp
index ebd12c4..581f285 100644
--- a/src/gpu/GrImageTextureMaker.cpp
+++ b/src/gpu/GrImageTextureMaker.cpp
@@ -40,7 +40,7 @@
 
 /////////////////////////////////////////////////////////////////////////////////////////////////
 
-GrYUVAImageTextureMaker::GrYUVAImageTextureMaker(GrContext* context, const SkImage* client)
+GrYUVAImageTextureMaker::GrYUVAImageTextureMaker(GrRecordingContext* context, const SkImage* client)
         : INHERITED(context, client->imageInfo())
         , fImage(static_cast<const SkImage_GpuYUVA*>(client)) {
     SkASSERT(as_IB(client)->isYUVA());
@@ -94,8 +94,9 @@
 
     const auto& caps = *fImage->context()->priv().caps();
     const SkMatrix& m = filterOrNullForBicubic ? textureMatrix : SkMatrix::I();
+    GrSamplerState sampler(wrapX, wrapY, filter);
     auto fp = GrYUVtoRGBEffect::Make(fImage->fViews, fImage->fYUVAIndices, fImage->fYUVColorSpace,
-                                     filter, caps, m, domain);
+                                     sampler, caps, m, domain);
     if (!filterOrNullForBicubic) {
         fp = GrBicubicEffect::Make(std::move(fp),
                                    fImage->alphaType(),
diff --git a/src/gpu/GrImageTextureMaker.h b/src/gpu/GrImageTextureMaker.h
index a84042f..8636b8a 100644
--- a/src/gpu/GrImageTextureMaker.h
+++ b/src/gpu/GrImageTextureMaker.h
@@ -33,7 +33,7 @@
 /** This class manages the conversion of generator-backed YUVA images to GrTextures. */
 class GrYUVAImageTextureMaker final : public GrTextureMaker {
 public:
-    GrYUVAImageTextureMaker(GrContext* context, const SkImage* client);
+    GrYUVAImageTextureMaker(GrRecordingContext* context, const SkImage* client);
 
     std::unique_ptr<GrFragmentProcessor> createFragmentProcessor(
             const SkMatrix& textureMatrix,
diff --git a/src/shaders/SkImageShader.cpp b/src/shaders/SkImageShader.cpp
index 698f22a..15bf848 100755
--- a/src/shaders/SkImageShader.cpp
+++ b/src/shaders/SkImageShader.cpp
@@ -5,6 +5,8 @@
  * found in the LICENSE file.
  */
 
+#include "src/shaders/SkImageShader.h"
+
 #include "src/core/SkArenaAlloc.h"
 #include "src/core/SkBitmapController.h"
 #include "src/core/SkColorSpacePriv.h"
@@ -13,12 +15,12 @@
 #include "src/core/SkOpts.h"
 #include "src/core/SkRasterPipeline.h"
 #include "src/core/SkReadBuffer.h"
+#include "src/core/SkScopeExit.h"
 #include "src/core/SkVM.h"
 #include "src/core/SkWriteBuffer.h"
 #include "src/image/SkImage_Base.h"
 #include "src/shaders/SkBitmapProcShader.h"
 #include "src/shaders/SkEmptyShader.h"
-#include "src/shaders/SkImageShader.h"
 
 /**
  *  We are faster in clamp, so always use that tiling when we can.
@@ -195,9 +197,12 @@
 #if SK_SUPPORT_GPU
 
 #include "include/private/GrRecordingContext.h"
+#include "src/gpu/GrBitmapTextureMaker.h"
 #include "src/gpu/GrCaps.h"
 #include "src/gpu/GrColorInfo.h"
+#include "src/gpu/GrImageTextureMaker.h"
 #include "src/gpu/GrRecordingContextPriv.h"
+#include "src/gpu/GrTextureAdjuster.h"
 #include "src/gpu/SkGr.h"
 #include "src/gpu/effects/GrBicubicEffect.h"
 #include "src/gpu/effects/GrTextureEffect.h"
@@ -210,51 +215,72 @@
         return nullptr;
     }
 
+    // This would all be much nicer with std::variant.
+    static constexpr size_t kSize = std::max({sizeof(GrYUVAImageTextureMaker),
+                                              sizeof(GrTextureAdjuster      ),
+                                              sizeof(GrImageTextureMaker    ),
+                                              sizeof(GrBitmapTextureMaker   )});
+    static constexpr size_t kAlign = std::max({alignof(GrYUVAImageTextureMaker),
+                                               alignof(GrTextureAdjuster      ),
+                                               alignof(GrImageTextureMaker    ),
+                                               alignof(GrBitmapTextureMaker   )});
+    std::aligned_storage_t<kSize, kAlign> storage;
+    GrTextureProducer* producer = nullptr;
+    SkScopeExit destroyProducer([&producer]{ if (producer) { producer->~GrTextureProducer(); } });
+
+    uint32_t pinnedUniqueID;
+    SkBitmap bm;
+    if (as_IB(fImage)->isYUVA()) {
+        producer = new (&storage) GrYUVAImageTextureMaker(args.fContext, fImage.get());
+    } else if (GrSurfaceProxyView view =
+                       as_IB(fImage)->refPinnedView(args.fContext, &pinnedUniqueID)) {
+        GrColorInfo colorInfo;
+        if (args.fContext->priv().caps()->isFormatSRGB(view.proxy()->backendFormat())) {
+            SkASSERT(fImage->colorType() == kRGBA_8888_SkColorType);
+            colorInfo = GrColorInfo(GrColorType::kRGBA_8888_SRGB, fImage->alphaType(),
+                                    fImage->refColorSpace());
+        } else {
+            colorInfo = fImage->imageInfo().colorInfo();
+        }
+        producer = new (&storage)
+                GrTextureAdjuster(args.fContext, std::move(view), colorInfo, pinnedUniqueID);
+    } else if (fImage->isLazyGenerated()) {
+        producer = new (&storage)
+                GrImageTextureMaker(args.fContext, fImage.get(), GrImageTexGenPolicy::kDraw);
+    } else if (as_IB(fImage)->getROPixels(&bm)) {
+        producer =
+                new (&storage) GrBitmapTextureMaker(args.fContext, bm, GrImageTexGenPolicy::kDraw);
+    } else {
+        return nullptr;
+    }
     GrSamplerState::WrapMode wmX = SkTileModeToWrapMode(fTileModeX),
                              wmY = SkTileModeToWrapMode(fTileModeY);
-
-    // Must set wrap and filter on the sampler before requesting a texture. In two places below
-    // we check the matrix scale factors to determine how to interpret the filter quality setting.
-    // This completely ignores the complexity of the drawVertices case where explicit local coords
-    // are provided by the caller.
+    // Must set wrap and filter on the sampler before requesting a texture. In two places
+    // below we check the matrix scale factors to determine how to interpret the filter
+    // quality setting. This completely ignores the complexity of the drawVertices case
+    // where explicit local coords are provided by the caller.
     bool doBicubic;
     GrSamplerState::Filter textureFilterMode = GrSkFilterQualityToGrFilterMode(
             fImage->width(), fImage->height(), this->resolveFiltering(args.fFilterQuality),
             args.fMatrixProvider.localToDevice(), *lm,
             args.fContext->priv().options().fSharpenMipmappedTextures, &doBicubic);
-    GrMipMapped mipMapped = GrMipMapped::kNo;
-    if (textureFilterMode == GrSamplerState::Filter::kMipMap) {
-        mipMapped = GrMipMapped::kYes;
-    }
-    GrSurfaceProxyView view = as_IB(fImage)->refView(args.fContext, mipMapped);
-    if (!view) {
+    const GrSamplerState::Filter* filterOrNull = doBicubic ? nullptr : &textureFilterMode;
+    auto fp = producer->createFragmentProcessor(lmInverse, SkRect::Make(fImage->dimensions()),
+                                                GrTextureProducer::kNo_FilterConstraint, false, wmX,
+                                                wmY, filterOrNull);
+
+    if (!fp) {
         return nullptr;
     }
-
-    SkAlphaType srcAlphaType = fImage->alphaType();
-
-    const auto& caps = *args.fContext->priv().caps();
-
-    std::unique_ptr<GrFragmentProcessor> inner;
-    if (doBicubic) {
-        static constexpr auto kDir    = GrBicubicEffect::Direction::kXY;
-        static constexpr auto kKernel = GrBicubicEffect::Kernel::kMitchell;
-        inner = GrBicubicEffect::Make(std::move(view), srcAlphaType, lmInverse, wmX, wmY, kKernel,
-                                      kDir, caps);
-    } else {
-        GrSamplerState samplerState(wmX, wmY, textureFilterMode);
-        inner = GrTextureEffect::Make(std::move(view), srcAlphaType, lmInverse, samplerState, caps);
-    }
-    inner = GrColorSpaceXformEffect::Make(std::move(inner), fImage->colorSpace(), srcAlphaType,
-                                          args.fDstColorInfo->colorSpace(), kPremul_SkAlphaType);
-
+    fp = GrColorSpaceXformEffect::Make(std::move(fp), fImage->colorSpace(), producer->alphaType(),
+                                       args.fDstColorInfo->colorSpace(), kPremul_SkAlphaType);
     bool isAlphaOnly = SkColorTypeIsAlphaOnly(fImage->colorType());
     if (isAlphaOnly) {
-        return inner;
+        return fp;
     } else if (args.fInputColorIsOpaque) {
-        return GrFragmentProcessor::OverrideInput(std::move(inner), SK_PMColor4fWHITE, false);
+        return GrFragmentProcessor::OverrideInput(std::move(fp), SK_PMColor4fWHITE, false);
     }
-    return GrFragmentProcessor::MulChildByInputAlpha(std::move(inner));
+    return GrFragmentProcessor::MulChildByInputAlpha(std::move(fp));
 }
 
 #endif
@@ -888,4 +914,3 @@
     SkColorSpaceXformSteps steps{cs,at, dst.colorSpace(),kPremul_SkAlphaType};
     return steps.program(p, uniforms, c);
 }
-