Reland "Delete legacy shadeSpan implementation of Perlin Noise."

Chromium was rebaselined at https://crrev.com/c/5323882.

Original change's description:
> Revert "Delete legacy shadeSpan implementation of Perlin Noise."
>
> This reverts commit 8589595721d09bd54ca694f75263846f400096da.
>
> Reason for revert: output visibly different
>
> Original change's description:
> > Delete legacy shadeSpan implementation of Perlin Noise.
> >
> > A CL was set up to rebaseline Chrome at https://crrev.com/c/5323882,
> > but it came up with zero image errors.
> >
> > Bug: b/40045243
> > Change-Id: I9c0ae2920ebaf56dcb931a57317ad2de0553d8f0
> > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/817622
> > Reviewed-by: Brian Osman <brianosman@google.com>
> > Commit-Queue: John Stiles <johnstiles@google.com>
>
> Bug: b/40045243
> Change-Id: I07e8e6abdadfa64693c18decd075a46fbee0e231
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/819520
> Auto-Submit: John Stiles <johnstiles@google.com>
> Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
> Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>

Bug: b/40045243
Change-Id: Ie6a29e9395c826d6352676ff7a41aadaff20481f
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/819644
Commit-Queue: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
diff --git a/relnotes/PerlinNoise.md b/relnotes/PerlinNoise.md
new file mode 100644
index 0000000..0cd18ab
--- /dev/null
+++ b/relnotes/PerlinNoise.md
@@ -0,0 +1,3 @@
+The Perlin noise shaders (`MakeFractalNoise` and `MakeTurbulence`) will now properly rotate when
+transformed. On raster surfaces, the performance of Perlin noise has also been significantly
+improved.
diff --git a/src/shaders/SkPerlinNoiseShaderImpl.cpp b/src/shaders/SkPerlinNoiseShaderImpl.cpp
index 275355a..2ce1251 100644
--- a/src/shaders/SkPerlinNoiseShaderImpl.cpp
+++ b/src/shaders/SkPerlinNoiseShaderImpl.cpp
@@ -12,39 +12,16 @@
 #include "include/core/SkRefCnt.h"
 #include "include/core/SkShader.h"
 #include "include/effects/SkPerlinNoiseShader.h"
-#include "include/private/base/SkCPUTypes.h"
-#include "include/private/base/SkTPin.h"
 #include "src/base/SkArenaAlloc.h"
-#include "src/core/SkReadBuffer.h"
-#include "src/core/SkWriteBuffer.h"
-#include "src/shaders/SkPerlinNoiseShaderType.h"
-
-#ifdef SK_RASTER_PIPELINE_PERLIN_NOISE
 #include "src/core/SkEffectPriv.h"
 #include "src/core/SkRasterPipeline.h"
 #include "src/core/SkRasterPipelineOpContexts.h"
 #include "src/core/SkRasterPipelineOpList.h"
+#include "src/core/SkReadBuffer.h"
+#include "src/core/SkWriteBuffer.h"
+#include "src/shaders/SkPerlinNoiseShaderType.h"
+
 #include <optional>
-#endif
-
-namespace {
-
-// noiseValue is the color component's value (or color)
-// limitValue is the maximum perlin noise array index value allowed
-// newValue is the current noise dimension (either width or height)
-inline int checkNoise(int noiseValue, int limitValue, int newValue) {
-    // If the noise value would bring us out of bounds of the current noise array while we are
-    // stiching noise tiles together, wrap the noise around the current dimension of the noise to
-    // stay within the array bounds in a continuous fashion (so that tiling lines are not visible)
-    if (noiseValue >= limitValue) {
-        noiseValue -= newValue;
-    }
-    return noiseValue;
-}
-
-inline SkScalar smoothCurve(SkScalar t) { return t * t * (3 - 2 * t); }
-
-}  // end namespace
 
 SkPerlinNoiseShader::SkPerlinNoiseShader(SkPerlinNoiseShaderType type,
                                          SkScalar baseFrequencyX,
@@ -103,162 +80,6 @@
     buffer.writeInt(fTileSize.fHeight);
 }
 
-SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::noise2D(int channel,
-                                                                const StitchData& stitchData,
-                                                                const SkPoint& noiseVector) const {
-    struct Noise {
-        int noisePositionIntegerValue;
-        int nextNoisePositionIntegerValue;
-        SkScalar noisePositionFractionValue;
-        Noise(SkScalar component) {
-            SkScalar position = component + kPerlinNoise;
-            noisePositionIntegerValue = SkScalarFloorToInt(position);
-            noisePositionFractionValue = position - SkIntToScalar(noisePositionIntegerValue);
-            nextNoisePositionIntegerValue = noisePositionIntegerValue + 1;
-        }
-    };
-    Noise noiseX(noiseVector.x());
-    Noise noiseY(noiseVector.y());
-    SkScalar u, v;
-    const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader);
-    // If stitching, adjust lattice points accordingly.
-    if (perlinNoiseShader.fStitchTiles) {
-        noiseX.noisePositionIntegerValue =
-                checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
-        noiseY.noisePositionIntegerValue =
-                checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
-        noiseX.nextNoisePositionIntegerValue = checkNoise(
-                noiseX.nextNoisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
-        noiseY.nextNoisePositionIntegerValue = checkNoise(
-                noiseY.nextNoisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
-    }
-    noiseX.noisePositionIntegerValue &= kBlockMask;
-    noiseY.noisePositionIntegerValue &= kBlockMask;
-    noiseX.nextNoisePositionIntegerValue &= kBlockMask;
-    noiseY.nextNoisePositionIntegerValue &= kBlockMask;
-    int i = fPaintingData.fLatticeSelector[noiseX.noisePositionIntegerValue];
-    int j = fPaintingData.fLatticeSelector[noiseX.nextNoisePositionIntegerValue];
-    int b00 = (i + noiseY.noisePositionIntegerValue) & kBlockMask;
-    int b10 = (j + noiseY.noisePositionIntegerValue) & kBlockMask;
-    int b01 = (i + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
-    int b11 = (j + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
-    SkScalar sx = smoothCurve(noiseX.noisePositionFractionValue);
-    SkScalar sy = smoothCurve(noiseY.noisePositionFractionValue);
-
-    if (sx < 0 || sy < 0 || sx > 1 || sy > 1) {
-        return 0;  // Check for pathological inputs.
-    }
-
-    // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement
-    SkPoint fractionValue = SkPoint::Make(noiseX.noisePositionFractionValue,
-                                          noiseY.noisePositionFractionValue);  // Offset (0,0)
-    u = fPaintingData.fGradient[channel][b00].dot(fractionValue);
-    fractionValue.fX -= SK_Scalar1;  // Offset (-1,0)
-    v = fPaintingData.fGradient[channel][b10].dot(fractionValue);
-    SkScalar a = SkScalarInterp(u, v, sx);
-    fractionValue.fY -= SK_Scalar1;  // Offset (-1,-1)
-    v = fPaintingData.fGradient[channel][b11].dot(fractionValue);
-    fractionValue.fX = noiseX.noisePositionFractionValue;  // Offset (0,-1)
-    u = fPaintingData.fGradient[channel][b01].dot(fractionValue);
-    SkScalar b = SkScalarInterp(u, v, sx);
-    return SkScalarInterp(a, b, sy);
-}
-
-SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::calculateTurbulenceValueForPoint(
-        int channel, StitchData& stitchData, const SkPoint& point) const {
-    const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader);
-    if (perlinNoiseShader.fStitchTiles) {
-        stitchData = fPaintingData.fStitchDataInit;
-    }
-    SkScalar turbulenceFunctionResult = 0;
-    SkPoint noiseVector(SkPoint::Make(point.x() * fPaintingData.fBaseFrequency.fX,
-                                      point.y() * fPaintingData.fBaseFrequency.fY));
-    SkScalar ratio = SK_Scalar1;
-    for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) {
-        SkScalar noise = noise2D(channel, stitchData, noiseVector);
-        SkScalar numer = (perlinNoiseShader.fType == SkPerlinNoiseShaderType::kFractalNoise)
-                                 ? noise
-                                 : SkScalarAbs(noise);
-        turbulenceFunctionResult += numer / ratio;
-        noiseVector.fX *= 2;
-        noiseVector.fY *= 2;
-        ratio *= 2;
-        if (perlinNoiseShader.fStitchTiles) {
-            stitchData = StitchData(SkIntToScalar(stitchData.fWidth) * 2,
-                                    SkIntToScalar(stitchData.fHeight) * 2);
-        }
-    }
-
-    if (perlinNoiseShader.fType == SkPerlinNoiseShaderType::kFractalNoise) {
-        // For kFractalNoise the result is: noise[-1,1] * 0.5 + 0.5
-        turbulenceFunctionResult = SkScalarHalf(turbulenceFunctionResult + 1);
-    }
-
-    if (channel == 3) {  // Scale alpha by paint value
-        turbulenceFunctionResult *= SkIntToScalar(getPaintAlpha()) / 255;
-    }
-
-    // Clamp result
-    return SkTPin(turbulenceFunctionResult, 0.0f, SK_Scalar1);
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-SkPMColor SkPerlinNoiseShader::PerlinNoiseShaderContext::shade(const SkPoint& point,
-                                                               StitchData& stitchData) const {
-    SkPoint newPoint;
-    fMatrix.mapPoints(&newPoint, &point, 1);
-    newPoint.fX = SkScalarRoundToScalar(newPoint.fX);
-    newPoint.fY = SkScalarRoundToScalar(newPoint.fY);
-
-    U8CPU rgba[4];
-    for (int channel = 3; channel >= 0; --channel) {
-        SkScalar value;
-        value = calculateTurbulenceValueForPoint(channel, stitchData, newPoint);
-        rgba[channel] = SkScalarFloorToInt(255 * value);
-    }
-    return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]);
-}
-
-#ifndef SK_RASTER_PIPELINE_PERLIN_NOISE  // TODO(b/40045243): enable in Chromium
-#ifdef SK_ENABLE_LEGACY_SHADERCONTEXT
-SkShaderBase::Context* SkPerlinNoiseShader::onMakeContext(const ContextRec& rec,
-                                                          SkArenaAlloc* alloc) const {
-    // should we pay attention to rec's device-colorspace?
-    return alloc->make<PerlinNoiseShaderContext>(*this, rec);
-}
-#endif
-#endif
-
-SkPerlinNoiseShader::PerlinNoiseShaderContext::PerlinNoiseShaderContext(
-        const SkPerlinNoiseShader& shader, const ContextRec& rec)
-        : Context(shader, rec)
-        , fMatrix(rec.fMatrixRec.totalMatrix())  // used for temp storage, adjusted below
-        , fPaintingData(shader.fTileSize,
-                        shader.fSeed,
-                        shader.fBaseFrequencyX,
-                        shader.fBaseFrequencyY,
-                        fMatrix) {
-    // This (1,1) translation is due to WebKit's 1 based coordinates for the noise
-    // (as opposed to 0 based, usually). The same adjustment is in the setData() function.
-    fMatrix.setTranslate(-fMatrix.getTranslateX() + SK_Scalar1,
-                         -fMatrix.getTranslateY() + SK_Scalar1);
-}
-
-void SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan(int x,
-                                                              int y,
-                                                              SkPMColor result[],
-                                                              int count) {
-    SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
-    StitchData stitchData;
-    for (int i = 0; i < count; ++i) {
-        result[i] = shade(point, stitchData);
-        point.fX += SK_Scalar1;
-    }
-}
-
-#ifdef SK_RASTER_PIPELINE_PERLIN_NOISE  // TODO(b/40045243): enable in Chromium
-
 bool SkPerlinNoiseShader::appendStages(const SkStageRec& rec,
                                        const SkShaders::MatrixRec& mRec) const {
     std::optional<SkShaders::MatrixRec> newMRec = mRec.apply(rec);
@@ -286,8 +107,6 @@
     return true;
 }
 
-#endif
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 static bool valid_input(
diff --git a/src/shaders/SkPerlinNoiseShaderImpl.h b/src/shaders/SkPerlinNoiseShaderImpl.h
index bdf2b04..4a6eaaf 100644
--- a/src/shaders/SkPerlinNoiseShaderImpl.h
+++ b/src/shaders/SkPerlinNoiseShaderImpl.h
@@ -9,7 +9,6 @@
 
 #include "include/core/SkAlphaType.h"
 #include "include/core/SkBitmap.h"
-#include "include/core/SkColor.h"
 #include "include/core/SkColorType.h"
 #include "include/core/SkFlattenable.h"
 #include "include/core/SkImageInfo.h"
@@ -20,6 +19,7 @@
 #include "include/core/SkTypes.h"
 #include "include/private/base/SkFloatingPoint.h"
 #include "include/private/base/SkMath.h"
+#include "include/private/base/SkOnce.h"
 #include "src/shaders/SkShaderBase.h"
 
 #include <algorithm>
@@ -27,15 +27,10 @@
 #include <cstring>
 #include <memory>
 
-class SkArenaAlloc;
 class SkReadBuffer;
 enum class SkPerlinNoiseShaderType;
-class SkWriteBuffer;
-
-#ifdef SK_RASTER_PIPELINE_PERLIN_NOISE
-#include "include/private/base/SkOnce.h"
 struct SkStageRec;
-#endif
+class SkWriteBuffer;
 
 class SkPerlinNoiseShader : public SkShaderBase {
 private:
@@ -46,7 +41,7 @@
 
 public:
     struct StitchData {
-        StitchData() : fWidth(0), fWrapX(0), fHeight(0), fWrapY(0) {}
+        StitchData() = default;
 
         StitchData(SkScalar w, SkScalar h)
                 : fWidth(std::min(SkScalarRoundToInt(w), SK_MaxS32 - kPerlinNoise))
@@ -59,10 +54,10 @@
                    fWrapY == other.fWrapY;
         }
 
-        int fWidth;  // How much to subtract to wrap for stitching.
-        int fWrapX;  // Minimum value to wrap.
-        int fHeight;
-        int fWrapY;
+        int fWidth = 0;  // How much to subtract to wrap for stitching.
+        int fWrapX = 0;  // Minimum value to wrap.
+        int fHeight = 0;
+        int fWrapY = 0;
     };
 
     struct PaintingData {
@@ -107,13 +102,11 @@
                 , fNoiseBitmap(that.fNoiseBitmap) {
             memcpy(fLatticeSelector, that.fLatticeSelector, sizeof(fLatticeSelector));
             memcpy(fNoise, that.fNoise, sizeof(fNoise));
-            memcpy(fGradient, that.fGradient, sizeof(fGradient));
         }
 
         int fSeed;
         uint8_t fLatticeSelector[kBlockSize];
         uint16_t fNoise[4][kBlockSize][2];
-        SkPoint fGradient[4][kBlockSize];
         SkISize fTileSize;
         SkVector fBaseFrequency;
         StitchData fStitchDataInit;
@@ -122,7 +115,7 @@
         SkBitmap fPermutationsBitmap;
         SkBitmap fNoiseBitmap;
 
-        inline int random() {
+        int random() {
             // See https://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement
             // m = kRandMaximum, 2**31 - 1 (2147483647)
             static constexpr int kRandAmplitude = 16807;  // 7**5; primitive root of m
@@ -192,15 +185,13 @@
             static constexpr SkScalar kInvBlockSizef = 1.0 / SkIntToScalar(kBlockSize);
             for (int channel = 0; channel < 4; ++channel) {
                 for (int i = 0; i < kBlockSize; ++i) {
-                    fGradient[channel][i] =
+                    SkPoint gradient =
                             SkPoint::Make((fNoise[channel][i][0] - kBlockSize) * kInvBlockSizef,
                                           (fNoise[channel][i][1] - kBlockSize) * kInvBlockSizef);
-                    fGradient[channel][i].normalize();
+                    gradient.normalize();
                     // Put the normalized gradient back into the noise data
-                    fNoise[channel][i][0] =
-                            SkScalarRoundToInt((fGradient[channel][i].fX + 1) * kHalfMax16bits);
-                    fNoise[channel][i][1] =
-                            SkScalarRoundToInt((fGradient[channel][i].fY + 1) * kHalfMax16bits);
+                    fNoise[channel][i][0] = SkScalarRoundToInt((gradient.fX + 1) * kHalfMax16bits);
+                    fNoise[channel][i][1] = SkScalarRoundToInt((gradient.fY + 1) * kHalfMax16bits);
                 }
             }
         }
@@ -265,25 +256,6 @@
 
     ShaderType type() const override { return ShaderType::kPerlinNoise; }
 
-    class PerlinNoiseShaderContext : public Context {
-    public:
-        PerlinNoiseShaderContext(const SkPerlinNoiseShader& shader, const ContextRec&);
-
-        void shadeSpan(int x, int y, SkPMColor[], int count) override;
-
-    private:
-        SkPMColor shade(const SkPoint& point, StitchData& stitchData) const;
-        SkScalar calculateTurbulenceValueForPoint(int channel,
-                                                  StitchData& stitchData,
-                                                  const SkPoint& point) const;
-        SkScalar noise2D(int channel,
-                         const StitchData& stitchData,
-                         const SkPoint& noiseVector) const;
-
-        SkMatrix fMatrix;
-        PaintingData fPaintingData;
-    };
-
     SkPerlinNoiseShaderType noiseType() const { return fType; }
     int numOctaves() const { return fNumOctaves; }
     bool stitchTiles() const { return fStitchTiles; }
@@ -296,17 +268,10 @@
                 fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY, mat);
     }
 
-#ifdef SK_RASTER_PIPELINE_PERLIN_NOISE
     bool appendStages(const SkStageRec& rec, const SkShaders::MatrixRec& mRec) const override;
-#endif
 
 protected:
     void flatten(SkWriteBuffer&) const override;
-#ifndef SK_RASTER_PIPELINE_PERLIN_NOISE  // TODO(b/40045243): enable in Chromium
-#ifdef SK_ENABLE_LEGACY_SHADERCONTEXT
-    Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override;
-#endif
-#endif
 
 private:
     SK_FLATTENABLE_HOOKS(SkPerlinNoiseShader)
@@ -319,10 +284,8 @@
     const SkISize fTileSize;
     const bool fStitchTiles;
 
-#ifdef SK_RASTER_PIPELINE_PERLIN_NOISE
     mutable SkOnce fInitPaintingDataOnce;
     std::unique_ptr<PaintingData> fPaintingData;
-#endif
 
     friend void SkRegisterPerlinNoiseShaderFlattenable();
 };