GrMatrixConvolutionEffect uses child for sampled kernel

Bug: skia:10139

Change-Id: Ic1380cf47c9293a54bf104ccbb3ca3222e704276
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/296127
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Adlai Holler <adlai@google.com>
diff --git a/src/gpu/effects/GrMatrixConvolutionEffect.cpp b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
index ed96861..1ad920e 100644
--- a/src/gpu/effects/GrMatrixConvolutionEffect.cpp
+++ b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
@@ -42,9 +42,12 @@
     typedef GrGLSLFragmentProcessor INHERITED;
 };
 
-GrMatrixConvolutionEffect::KernelWrapper GrMatrixConvolutionEffect::KernelWrapper::Make(
-        GrRecordingContext* context, SkISize size, const GrCaps& caps, const SkScalar* values) {
-    if (nullptr == context || nullptr == values || size.isEmpty()) {
+GrMatrixConvolutionEffect::KernelWrapper::MakeResult
+GrMatrixConvolutionEffect::KernelWrapper::Make(GrRecordingContext* context,
+                                               SkISize size,
+                                               const GrCaps& caps,
+                                               const SkScalar* values) {
+    if (!context || !values || size.isEmpty()) {
         return {};
     }
     const int length = size.area();
@@ -54,10 +57,10 @@
         for (int i = 0; i < length; i++) {
             result.fArray[i] = SkScalarToFloat(values[i]);
         }
-        return result;
+        return {result, nullptr};
     }
 
-    ScalableSampler& scalableSampler = result.fScalableSampler;
+    BiasAndGain& scalableSampler = result.fBiasAndGain;
     bool useA16 =
         context->defaultBackendFormat(kA16_float_SkColorType, GrRenderable::kNo).isValid();
     SkScalar min = values[0];
@@ -108,8 +111,7 @@
         view = {std::move(cachedKernel), kTopLeft_GrSurfaceOrigin, swizzle};
     } else {
         SkBitmap bm;
-        auto info = SkImageInfo::Make({(int)GrNextPow2(length), 1}, colorType,
-                                      kPremul_SkAlphaType, nullptr);
+        auto info = SkImageInfo::Make({length, 1}, colorType, kPremul_SkAlphaType, nullptr);
         if (!bm.tryAllocPixels(info)) {
             return {};
         }
@@ -131,23 +133,23 @@
             proxyProvider->assignUniqueKeyToProxy(key, view.asTextureProxy());
         }
     }
-    scalableSampler.fSampler = { std::move(view) };
-    return result;
+    auto kernelFP = GrTextureEffect::Make(std::move(view), kUnknown_SkAlphaType);
+    return {result, std::move(kernelFP)};
 }
 
 bool GrMatrixConvolutionEffect::KernelWrapper::operator==(const KernelWrapper& k) const {
     if (fSize != k.fSize) {
         return false;
     } else if (this->isSampled()) {
-        return fScalableSampler == k.fScalableSampler;
+        return fBiasAndGain == k.fBiasAndGain;
     } else {
         return std::equal(fArray.begin(), fArray.begin() + fSize.area(), k.fArray.begin());
     }
 }
 
-bool GrMatrixConvolutionEffect::KernelWrapper::ScalableSampler::operator==(
-                                                                const ScalableSampler& k) const {
-    return fSampler == k.fSampler && fGain == k.fGain && fBias == k.fBias;
+bool GrMatrixConvolutionEffect::KernelWrapper::BiasAndGain::operator==(
+                                                                const BiasAndGain& k) const {
+    return fGain == k.fGain && fBias == k.fBias;
 }
 
 // For sampled kernels, emit a for loop that does all the kernel accumulation.
@@ -162,7 +164,6 @@
     int kernelArea = kernelWidth * kernelHeight;
 
     if (mce.kernelIsSampled()) {
-        fragBuilder->codeAppendf("half2 kernelCoord = half2(0, 0);");
         fragBuilder->codeAppendf("for (int i = 0; i < %d; ++i)", (int)kernelArea);
     }
 
@@ -172,13 +173,11 @@
     fragBuilder->codeAppend("half2 sourceOffset;");
     if (mce.kernelIsSampled()) {
         const char* kernelBias = uniformHandler->getUniformCStr(fKernelBiasUni);
-        fragBuilder->codeAppend("k = ");
-        fragBuilder->appendTextureLookup(args.fTexSamplers[0], "kernelCoord");
-        fragBuilder->codeAppendf(".w + %s;", kernelBias);
+        SkString kernelCoord = SkStringPrintf("float2(float(i) + 0.5, 0.5)");
+        SkString kernelSample = this->invokeChild(1, args, kernelCoord.c_str());
+        fragBuilder->codeAppendf("k = %s.w + %s;", kernelSample.c_str(), kernelBias);
         fragBuilder->codeAppendf("sourceOffset.y = floor(i / %d);", kernelWidth);
         fragBuilder->codeAppendf("sourceOffset.x = i - sourceOffset.y * %d;", kernelWidth);
-        float kernelStride = 1.0f / (float)GrNextPow2(kernelArea);
-        fragBuilder->codeAppendf("kernelCoord.x += %f;", kernelStride);
     } else {
         fragBuilder->codeAppendf("sourceOffset = half2(%d, %d);", loc.x(), loc.y());
         int offset = loc.y() * kernelWidth + loc.x();
@@ -282,7 +281,8 @@
 }
 
 GrMatrixConvolutionEffect::GrMatrixConvolutionEffect(std::unique_ptr<GrFragmentProcessor> child,
-                                                     KernelWrapper kernel,
+                                                     const KernelWrapper& kernel,
+                                                     std::unique_ptr<GrFragmentProcessor> kernelFP,
                                                      SkScalar gain,
                                                      SkScalar bias,
                                                      const SkIPoint& kernelOffset,
@@ -290,14 +290,15 @@
         // To advertise either the modulation or opaqueness optimizations we'd have to examine the
         // parameters.
         : INHERITED(kGrMatrixConvolutionEffect_ClassID, kNone_OptimizationFlags)
-        , fKernel(std::move(kernel))
+        , fKernel(kernel)
         , fGain(SkScalarToFloat(gain))
         , fBias(SkScalarToFloat(bias) / 255.0f)
         , fConvolveAlpha(convolveAlpha) {
     child->setSampledWithExplicitCoords();
     this->registerChildProcessor(std::move(child));
-    if (fKernel.isSampled()) {
-        this->setTextureSamplerCnt(1);
+    if (kernelFP) {
+        kernelFP->setSampledWithExplicitCoords();
+        this->registerChildProcessor(std::move(kernelFP));
     }
     fKernelOffset = {static_cast<float>(kernelOffset.x()),
                      static_cast<float>(kernelOffset.y())};
@@ -315,7 +316,9 @@
     child->setSampledWithExplicitCoords();
     this->registerChildProcessor(std::move(child));
     if (fKernel.isSampled()) {
-        this->setTextureSamplerCnt(1);
+        child = that.childProcessor(1).clone();
+        child->setSampledWithExplicitCoords();
+        this->registerChildProcessor(std::move(child));
     }
     this->addCoordTransform(&fCoordTransform);
 }
@@ -342,11 +345,6 @@
            fConvolveAlpha == s.convolveAlpha();
 }
 
-const GrFragmentProcessor::TextureSampler& GrMatrixConvolutionEffect::onTextureSampler(
-        int index) const {
-    return IthTextureSampler(index, fKernel.scalableSampler().fSampler);
-}
-
 static void fill_in_1D_gaussian_kernel_with_stride(float* kernel, int size, int stride,
                                                    float twoSigmaSqrd) {
     SkASSERT(!SkScalarNearlyZero(twoSigmaSqrd, SK_ScalarNearlyZero));
@@ -437,15 +435,16 @@
                                                                      GrSamplerState::WrapMode wm,
                                                                      bool convolveAlpha,
                                                                      const GrCaps& caps) {
-    auto kw = KernelWrapper::Make(context, kernelSize, caps, kernel);
-    if (!kw.isValid()) {
+    auto [kernelWrapper, kernelFP] = KernelWrapper::Make(context, kernelSize, caps, kernel);
+    if (!kernelWrapper.isValid()) {
         return nullptr;
     }
     GrSamplerState sampler(wm, GrSamplerState::Filter::kNearest);
     auto child = GrTextureEffect::MakeSubset(std::move(srcView), kPremul_SkAlphaType, SkMatrix::I(),
                                              sampler, SkRect::Make(srcBounds), caps);
-    return std::unique_ptr<GrFragmentProcessor>(new GrMatrixConvolutionEffect(
-            std::move(child), std::move(kw), gain, bias, kernelOffset, convolveAlpha));
+    return std::unique_ptr<GrFragmentProcessor>(
+            new GrMatrixConvolutionEffect(std::move(child), kernelWrapper, std::move(kernelFP),
+                                          gain, bias, kernelOffset, convolveAlpha));
 }
 
 std::unique_ptr<GrFragmentProcessor> GrMatrixConvolutionEffect::MakeGaussian(