1e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com/*
2e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * Copyright 2013 Google Inc.
3e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com *
4e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * Use of this source code is governed by a BSD-style license that can be
5e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * found in the LICENSE file.
6e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com */
7e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
8e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#include "SkPerlinNoiseShader.h"
9c2a0ea6418988d4bcc0719f99b1a110cecd08679commit-bot@chromium.org#include "SkColorFilter.h"
108b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
12e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#include "SkShader.h"
13e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#include "SkUnPreMultiply.h"
14e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#include "SkString.h"
15e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
16e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#if SK_SUPPORT_GPU
17e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#include "GrContext.h"
1877af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com#include "GrCoordTransform.h"
19605dd0fbce9dbb2a0d3313e13e161f2bd54870d7egdaniel#include "GrInvariantOutput.h"
20eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "SkGr.h"
21c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon#include "effects/GrConstColorProcessor.h"
2264c4728c70001ed074fecf5c4e083781987b12e9egdaniel#include "glsl/GrGLSLFragmentProcessor.h"
232d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel#include "glsl/GrGLSLFragmentShaderBuilder.h"
24018fb62d12d1febf121fe265da5b6117b86a6541egdaniel#include "glsl/GrGLSLProgramDataManager.h"
257ea439b2203855db97330b25945b87dd4b170b8begdaniel#include "glsl/GrGLSLUniformHandler.h"
26e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#endif
27e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
28e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comstatic const int kBlockSize = 256;
29e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comstatic const int kBlockMask = kBlockSize - 1;
30e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comstatic const int kPerlinNoise = 4096;
31e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comstatic const int kRandMaximum = SK_MaxS32; // 2**31 - 1
32e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
33e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comnamespace {
34e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
35e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com// noiseValue is the color component's value (or color)
36e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com// limitValue is the maximum perlin noise array index value allowed
37e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com// newValue is the current noise dimension (either width or height)
38e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.cominline int checkNoise(int noiseValue, int limitValue, int newValue) {
39e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // If the noise value would bring us out of bounds of the current noise array while we are
40e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // stiching noise tiles together, wrap the noise around the current dimension of the noise to
41e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // stay within the array bounds in a continuous fashion (so that tiling lines are not visible)
42e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    if (noiseValue >= limitValue) {
43e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        noiseValue -= newValue;
44e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
45e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    return noiseValue;
46e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}
47e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
48e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.cominline SkScalar smoothCurve(SkScalar t) {
494b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org    static const SkScalar SK_Scalar3 = 3.0f;
50e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
51e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // returns t * t * (3 - 2 * t)
52e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    return SkScalarMul(SkScalarSquare(t), SK_Scalar3 - 2 * t);
53e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}
54e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
55e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} // end namespace
56e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
57e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comstruct SkPerlinNoiseShader::StitchData {
58e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    StitchData()
59e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com      : fWidth(0)
60e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com      , fWrapX(0)
61e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com      , fHeight(0)
62e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com      , fWrapY(0)
63e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    {}
64e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
65e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    bool operator==(const StitchData& other) const {
66e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        return fWidth == other.fWidth &&
67e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com               fWrapX == other.fWrapX &&
68e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com               fHeight == other.fHeight &&
69e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com               fWrapY == other.fWrapY;
70e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
71e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
72e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    int fWidth; // How much to subtract to wrap for stitching.
73e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    int fWrapX; // Minimum value to wrap.
74e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    int fHeight;
75e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    int fWrapY;
76e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com};
77e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
78e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comstruct SkPerlinNoiseShader::PaintingData {
79fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org    PaintingData(const SkISize& tileSize, SkScalar seed,
80ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco                 SkScalar baseFrequencyX, SkScalar baseFrequencyY,
81ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco                 const SkMatrix& matrix)
82e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    {
8311fa2247b747eb75e2f158dc7571d458ed6c0115reed        SkVector vec[2] = {
8411fa2247b747eb75e2f158dc7571d458ed6c0115reed            { SkScalarInvert(baseFrequencyX),   SkScalarInvert(baseFrequencyY)  },
8511fa2247b747eb75e2f158dc7571d458ed6c0115reed            { SkIntToScalar(tileSize.fWidth),   SkIntToScalar(tileSize.fHeight) },
8611fa2247b747eb75e2f158dc7571d458ed6c0115reed        };
8711fa2247b747eb75e2f158dc7571d458ed6c0115reed        matrix.mapVectors(vec, 2);
8811fa2247b747eb75e2f158dc7571d458ed6c0115reed
8911fa2247b747eb75e2f158dc7571d458ed6c0115reed        fBaseFrequency.set(SkScalarInvert(vec[0].fX), SkScalarInvert(vec[0].fY));
9011fa2247b747eb75e2f158dc7571d458ed6c0115reed        fTileSize.set(SkScalarRoundToInt(vec[1].fX), SkScalarRoundToInt(vec[1].fY));
91fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org        this->init(seed);
92fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org        if (!fTileSize.isEmpty()) {
93fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org            this->stitch();
94fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org        }
95fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org
96f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco#if SK_SUPPORT_GPU
97a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org        fPermutationsBitmap.setInfo(SkImageInfo::MakeA8(kBlockSize, 1));
98fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org        fPermutationsBitmap.setPixels(fLatticeSelector);
99fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org
100a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org        fNoiseBitmap.setInfo(SkImageInfo::MakeN32Premul(kBlockSize, 4));
101fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org        fNoiseBitmap.setPixels(fNoise[0][0]);
102fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org#endif
103e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
104e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
105e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    int         fSeed;
106e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    uint8_t     fLatticeSelector[kBlockSize];
107e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    uint16_t    fNoise[4][kBlockSize][2];
108e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    SkPoint     fGradient[4][kBlockSize];
109e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    SkISize     fTileSize;
110e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    SkVector    fBaseFrequency;
111e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    StitchData  fStitchDataInit;
112e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
113e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comprivate:
114e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
115f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco#if SK_SUPPORT_GPU
116fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org    SkBitmap   fPermutationsBitmap;
117fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org    SkBitmap   fNoiseBitmap;
118fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org#endif
119e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
120e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    inline int random()  {
121e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        static const int gRandAmplitude = 16807; // 7**5; primitive root of m
122e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        static const int gRandQ = 127773; // m / a
123e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        static const int gRandR = 2836; // m % a
124e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
125e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        int result = gRandAmplitude * (fSeed % gRandQ) - gRandR * (fSeed / gRandQ);
126e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        if (result <= 0)
127e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            result += kRandMaximum;
128e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        fSeed = result;
129e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        return result;
130e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
131e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
132fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org    // Only called once. Could be part of the constructor.
133e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    void init(SkScalar seed)
134e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    {
135e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        static const SkScalar gInvBlockSizef = SkScalarInvert(SkIntToScalar(kBlockSize));
136e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
137857e320300372dab938c0dbffadc3c2c8a893b92senorblanco@chromium.org        // According to the SVG spec, we must truncate (not round) the seed value.
138857e320300372dab938c0dbffadc3c2c8a893b92senorblanco@chromium.org        fSeed = SkScalarTruncToInt(seed);
139e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        // The seed value clamp to the range [1, kRandMaximum - 1].
140e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        if (fSeed <= 0) {
141e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            fSeed = -(fSeed % (kRandMaximum - 1)) + 1;
142e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        }
143e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        if (fSeed > kRandMaximum - 1) {
144e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            fSeed = kRandMaximum - 1;
145e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        }
146e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        for (int channel = 0; channel < 4; ++channel) {
147e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            for (int i = 0; i < kBlockSize; ++i) {
148e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                fLatticeSelector[i] = i;
149e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                fNoise[channel][i][0] = (random() % (2 * kBlockSize));
150e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                fNoise[channel][i][1] = (random() % (2 * kBlockSize));
151e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            }
152e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        }
153e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        for (int i = kBlockSize - 1; i > 0; --i) {
154e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            int k = fLatticeSelector[i];
155e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            int j = random() % kBlockSize;
156e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            SkASSERT(j >= 0);
157e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            SkASSERT(j < kBlockSize);
158e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            fLatticeSelector[i] = fLatticeSelector[j];
159e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            fLatticeSelector[j] = k;
160e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        }
161e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
162e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        // Perform the permutations now
163e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        {
164e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            // Copy noise data
165e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            uint16_t noise[4][kBlockSize][2];
166e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            for (int i = 0; i < kBlockSize; ++i) {
167e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                for (int channel = 0; channel < 4; ++channel) {
168e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                    for (int j = 0; j < 2; ++j) {
169e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                        noise[channel][i][j] = fNoise[channel][i][j];
170e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                    }
171e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                }
172e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            }
173e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            // Do permutations on noise data
174e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            for (int i = 0; i < kBlockSize; ++i) {
175e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                for (int channel = 0; channel < 4; ++channel) {
176e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                    for (int j = 0; j < 2; ++j) {
177e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                        fNoise[channel][i][j] = noise[channel][fLatticeSelector[i]][j];
178e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                    }
179e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                }
180e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            }
181e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        }
182e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
183e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        // Half of the largest possible value for 16 bit unsigned int
1844b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org        static const SkScalar gHalfMax16bits = 32767.5f;
185e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
186e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        // Compute gradients from permutated noise data
187e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        for (int channel = 0; channel < 4; ++channel) {
188e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            for (int i = 0; i < kBlockSize; ++i) {
189e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                fGradient[channel][i] = SkPoint::Make(
190e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                    SkScalarMul(SkIntToScalar(fNoise[channel][i][0] - kBlockSize),
191e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                                gInvBlockSizef),
192cff0243b0ff1de25b3d99e2bf15a30c0e0a31261skia.committer@gmail.com                    SkScalarMul(SkIntToScalar(fNoise[channel][i][1] - kBlockSize),
193e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                                gInvBlockSizef));
194e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                fGradient[channel][i].normalize();
195e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                // Put the normalized gradient back into the noise data
196e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                fNoise[channel][i][0] = SkScalarRoundToInt(SkScalarMul(
197d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com                    fGradient[channel][i].fX + SK_Scalar1, gHalfMax16bits));
198e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                fNoise[channel][i][1] = SkScalarRoundToInt(SkScalarMul(
199d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com                    fGradient[channel][i].fY + SK_Scalar1, gHalfMax16bits));
200e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            }
201e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        }
202e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
203e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
204fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org    // Only called once. Could be part of the constructor.
205e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    void stitch() {
206e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        SkScalar tileWidth  = SkIntToScalar(fTileSize.width());
207e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        SkScalar tileHeight = SkIntToScalar(fTileSize.height());
208e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        SkASSERT(tileWidth > 0 && tileHeight > 0);
209e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        // When stitching tiled turbulence, the frequencies must be adjusted
210e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        // so that the tile borders will be continuous.
211e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        if (fBaseFrequency.fX) {
2128015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com            SkScalar lowFrequencx =
2138015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com                SkScalarFloorToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
2148015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com            SkScalar highFrequencx =
2158015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com                SkScalarCeilToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
216e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            // BaseFrequency should be non-negative according to the standard.
21780ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed            if (fBaseFrequency.fX / lowFrequencx < highFrequencx / fBaseFrequency.fX) {
218e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                fBaseFrequency.fX = lowFrequencx;
219e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            } else {
220e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                fBaseFrequency.fX = highFrequencx;
221e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            }
222e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        }
223e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        if (fBaseFrequency.fY) {
2248015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com            SkScalar lowFrequency =
2258015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com                SkScalarFloorToScalar(tileHeight * fBaseFrequency.fY) / tileHeight;
2268015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com            SkScalar highFrequency =
2278015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com                SkScalarCeilToScalar(tileHeight * fBaseFrequency.fY) / tileHeight;
22880ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed            if (fBaseFrequency.fY / lowFrequency < highFrequency / fBaseFrequency.fY) {
229e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                fBaseFrequency.fY = lowFrequency;
230e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            } else {
231e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                fBaseFrequency.fY = highFrequency;
232e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            }
233e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        }
234e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        // Set up TurbulenceInitial stitch values.
235e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        fStitchDataInit.fWidth  =
2368015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com            SkScalarRoundToInt(tileWidth * fBaseFrequency.fX);
237e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        fStitchDataInit.fWrapX  = kPerlinNoise + fStitchDataInit.fWidth;
238e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        fStitchDataInit.fHeight =
2398015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com            SkScalarRoundToInt(tileHeight * fBaseFrequency.fY);
240e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        fStitchDataInit.fWrapY  = kPerlinNoise + fStitchDataInit.fHeight;
241e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
242e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
243fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.orgpublic:
244e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
245f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco#if SK_SUPPORT_GPU
246fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org    const SkBitmap& getPermutationsBitmap() const { return fPermutationsBitmap; }
247fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org
248fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org    const SkBitmap& getNoiseBitmap() const { return fNoiseBitmap; }
249fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org#endif
250e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com};
251e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
252e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comSkShader* SkPerlinNoiseShader::CreateFractalNoise(SkScalar baseFrequencyX, SkScalar baseFrequencyY,
253e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                                                  int numOctaves, SkScalar seed,
254e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                                                  const SkISize* tileSize) {
255385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    return new SkPerlinNoiseShader(kFractalNoise_Type, baseFrequencyX, baseFrequencyY, numOctaves,
256385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary                                   seed, tileSize);
257e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}
258e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
2599fbbcca1c958e6df2cff24d3ccdb7ebd89b8486bcommit-bot@chromium.orgSkShader* SkPerlinNoiseShader::CreateTurbulence(SkScalar baseFrequencyX, SkScalar baseFrequencyY,
260e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                                              int numOctaves, SkScalar seed,
261e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                                              const SkISize* tileSize) {
262385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    return new SkPerlinNoiseShader(kTurbulence_Type, baseFrequencyX, baseFrequencyY, numOctaves,
263385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary                                   seed, tileSize);
264e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}
265e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
266e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comSkPerlinNoiseShader::SkPerlinNoiseShader(SkPerlinNoiseShader::Type type,
267e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                                         SkScalar baseFrequencyX,
268e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                                         SkScalar baseFrequencyY,
269e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                                         int numOctaves,
270e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                                         SkScalar seed,
271e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                                         const SkISize* tileSize)
272e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com  : fType(type)
273e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com  , fBaseFrequencyX(baseFrequencyX)
274e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com  , fBaseFrequencyY(baseFrequencyY)
275ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org  , fNumOctaves(numOctaves > 255 ? 255 : numOctaves/*[0,255] octaves allowed*/)
276e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com  , fSeed(seed)
27796fcdcc219d2a0d3579719b84b28bede76efba64halcanary  , fTileSize(nullptr == tileSize ? SkISize::Make(0, 0) : *tileSize)
278fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org  , fStitchTiles(!fTileSize.isEmpty())
279e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com{
280e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    SkASSERT(numOctaves >= 0 && numOctaves < 256);
281e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}
282e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
283e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comSkPerlinNoiseShader::~SkPerlinNoiseShader() {
284e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}
285e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
2869fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkPerlinNoiseShader::CreateProc(SkReadBuffer& buffer) {
2879fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    Type type = (Type)buffer.readInt();
2889fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkScalar freqX = buffer.readScalar();
2899fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkScalar freqY = buffer.readScalar();
2909fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    int octaves = buffer.readInt();
2919fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkScalar seed = buffer.readScalar();
2929fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkISize tileSize;
2939fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    tileSize.fWidth = buffer.readInt();
2949fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    tileSize.fHeight = buffer.readInt();
2959fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
2969fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    switch (type) {
2979fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        case kFractalNoise_Type:
2989fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed            return SkPerlinNoiseShader::CreateFractalNoise(freqX, freqY, octaves, seed, &tileSize);
2999fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        case kTurbulence_Type:
3009fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed            return SkPerlinNoiseShader::CreateTubulence(freqX, freqY, octaves, seed, &tileSize);
3019fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        default:
30296fcdcc219d2a0d3579719b84b28bede76efba64halcanary            return nullptr;
3039fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
3049fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
3059fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
3068b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkPerlinNoiseShader::flatten(SkWriteBuffer& buffer) const {
307e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    buffer.writeInt((int) fType);
308e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    buffer.writeScalar(fBaseFrequencyX);
309e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    buffer.writeScalar(fBaseFrequencyY);
310e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    buffer.writeInt(fNumOctaves);
311e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    buffer.writeScalar(fSeed);
312e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    buffer.writeInt(fTileSize.fWidth);
313e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    buffer.writeInt(fTileSize.fHeight);
314e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}
315e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
31687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::noise2D(
317ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco        int channel, const StitchData& stitchData, const SkPoint& noiseVector) const {
318e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    struct Noise {
319e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        int noisePositionIntegerValue;
320ce6a354e121915c2925e545e7df2929492d69d50senorblanco        int nextNoisePositionIntegerValue;
321e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        SkScalar noisePositionFractionValue;
322e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        Noise(SkScalar component)
323e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        {
324e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            SkScalar position = component + kPerlinNoise;
325e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            noisePositionIntegerValue = SkScalarFloorToInt(position);
326e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            noisePositionFractionValue = position - SkIntToScalar(noisePositionIntegerValue);
327ce6a354e121915c2925e545e7df2929492d69d50senorblanco            nextNoisePositionIntegerValue = noisePositionIntegerValue + 1;
328e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        }
329e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    };
330e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    Noise noiseX(noiseVector.x());
331e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    Noise noiseY(noiseVector.y());
332e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    SkScalar u, v;
33387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader);
334e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // If stitching, adjust lattice points accordingly.
33587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    if (perlinNoiseShader.fStitchTiles) {
336e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        noiseX.noisePositionIntegerValue =
337e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
338e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        noiseY.noisePositionIntegerValue =
339e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
340ce6a354e121915c2925e545e7df2929492d69d50senorblanco        noiseX.nextNoisePositionIntegerValue =
341ce6a354e121915c2925e545e7df2929492d69d50senorblanco            checkNoise(noiseX.nextNoisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
342ce6a354e121915c2925e545e7df2929492d69d50senorblanco        noiseY.nextNoisePositionIntegerValue =
343ce6a354e121915c2925e545e7df2929492d69d50senorblanco            checkNoise(noiseY.nextNoisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
344e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
345e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    noiseX.noisePositionIntegerValue &= kBlockMask;
346e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    noiseY.noisePositionIntegerValue &= kBlockMask;
347ce6a354e121915c2925e545e7df2929492d69d50senorblanco    noiseX.nextNoisePositionIntegerValue &= kBlockMask;
348ce6a354e121915c2925e545e7df2929492d69d50senorblanco    noiseY.nextNoisePositionIntegerValue &= kBlockMask;
349ce6a354e121915c2925e545e7df2929492d69d50senorblanco    int i =
350ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco        fPaintingData->fLatticeSelector[noiseX.noisePositionIntegerValue];
351ce6a354e121915c2925e545e7df2929492d69d50senorblanco    int j =
352ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco        fPaintingData->fLatticeSelector[noiseX.nextNoisePositionIntegerValue];
353ce6a354e121915c2925e545e7df2929492d69d50senorblanco    int b00 = (i + noiseY.noisePositionIntegerValue) & kBlockMask;
354ce6a354e121915c2925e545e7df2929492d69d50senorblanco    int b10 = (j + noiseY.noisePositionIntegerValue) & kBlockMask;
355ce6a354e121915c2925e545e7df2929492d69d50senorblanco    int b01 = (i + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
356ce6a354e121915c2925e545e7df2929492d69d50senorblanco    int b11 = (j + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
357e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    SkScalar sx = smoothCurve(noiseX.noisePositionFractionValue);
358e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    SkScalar sy = smoothCurve(noiseY.noisePositionFractionValue);
359e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement
360e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    SkPoint fractionValue = SkPoint::Make(noiseX.noisePositionFractionValue,
361e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                                          noiseY.noisePositionFractionValue); // Offset (0,0)
362ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco    u = fPaintingData->fGradient[channel][b00].dot(fractionValue);
363e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    fractionValue.fX -= SK_Scalar1; // Offset (-1,0)
364ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco    v = fPaintingData->fGradient[channel][b10].dot(fractionValue);
365e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    SkScalar a = SkScalarInterp(u, v, sx);
366e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    fractionValue.fY -= SK_Scalar1; // Offset (-1,-1)
367ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco    v = fPaintingData->fGradient[channel][b11].dot(fractionValue);
368e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1)
369ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco    u = fPaintingData->fGradient[channel][b01].dot(fractionValue);
370e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    SkScalar b = SkScalarInterp(u, v, sx);
371e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    return SkScalarInterp(a, b, sy);
372e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}
373e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
37487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::calculateTurbulenceValueForPoint(
375ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco        int channel, StitchData& stitchData, const SkPoint& point) const {
37687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader);
37787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    if (perlinNoiseShader.fStitchTiles) {
378e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        // Set up TurbulenceInitial stitch values.
379ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco        stitchData = fPaintingData->fStitchDataInit;
380e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
381e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    SkScalar turbulenceFunctionResult = 0;
382ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco    SkPoint noiseVector(SkPoint::Make(SkScalarMul(point.x(), fPaintingData->fBaseFrequency.fX),
383ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco                                      SkScalarMul(point.y(), fPaintingData->fBaseFrequency.fY)));
384e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    SkScalar ratio = SK_Scalar1;
38587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) {
386ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco        SkScalar noise = noise2D(channel, stitchData, noiseVector);
38780ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed        SkScalar numer = (perlinNoiseShader.fType == kFractalNoise_Type) ?
38880ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed                            noise : SkScalarAbs(noise);
38980ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed        turbulenceFunctionResult += numer / ratio;
390e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        noiseVector.fX *= 2;
391e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        noiseVector.fY *= 2;
392e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        ratio *= 2;
39387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        if (perlinNoiseShader.fStitchTiles) {
394e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            // Update stitch values
395e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            stitchData.fWidth  *= 2;
396e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            stitchData.fWrapX   = stitchData.fWidth + kPerlinNoise;
397e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            stitchData.fHeight *= 2;
398e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            stitchData.fWrapY   = stitchData.fHeight + kPerlinNoise;
399e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        }
400e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
401e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
402e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
403e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // by fractalNoise and (turbulenceFunctionResult) by turbulence.
40487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    if (perlinNoiseShader.fType == kFractalNoise_Type) {
405e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        turbulenceFunctionResult =
406e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            SkScalarMul(turbulenceFunctionResult, SK_ScalarHalf) + SK_ScalarHalf;
407e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
408e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
409e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    if (channel == 3) { // Scale alpha by paint value
41080ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed        turbulenceFunctionResult *= SkIntToScalar(getPaintAlpha()) / 255;
411e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
412e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
413e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // Clamp result
414e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1);
415e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}
416e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
41787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkPMColor SkPerlinNoiseShader::PerlinNoiseShaderContext::shade(
41887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        const SkPoint& point, StitchData& stitchData) const {
419e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    SkPoint newPoint;
420a8d95f899bf3fe404d3cd5c357531ff852c15b29senorblanco@chromium.org    fMatrix.mapPoints(&newPoint, &point, 1);
421e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    newPoint.fX = SkScalarRoundToScalar(newPoint.fX);
422e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    newPoint.fY = SkScalarRoundToScalar(newPoint.fY);
423e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
424e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    U8CPU rgba[4];
425e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    for (int channel = 3; channel >= 0; --channel) {
426e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        rgba[channel] = SkScalarFloorToInt(255 *
427ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco            calculateTurbulenceValueForPoint(channel, stitchData, newPoint));
428e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
429e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]);
430e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}
431e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
432ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.orgSkShader::Context* SkPerlinNoiseShader::onCreateContext(const ContextRec& rec,
433ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org                                                        void* storage) const {
434385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    return new (storage) PerlinNoiseShaderContext(*this, rec);
43587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org}
43687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
4378d9f2e474ac9d175c28079357b022d31408e2fe4fmalitasize_t SkPerlinNoiseShader::contextSize(const ContextRec&) const {
43887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    return sizeof(PerlinNoiseShaderContext);
43987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org}
44087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
44187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkPerlinNoiseShader::PerlinNoiseShaderContext::PerlinNoiseShaderContext(
442e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org        const SkPerlinNoiseShader& shader, const ContextRec& rec)
443e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org    : INHERITED(shader, rec)
44487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org{
445e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org    SkMatrix newMatrix = *rec.fMatrix;
446b67b8e6052bf5567eb3f9726dda99a6b260dfb05reed@google.com    newMatrix.preConcat(shader.getLocalMatrix());
447b67b8e6052bf5567eb3f9726dda99a6b260dfb05reed@google.com    if (rec.fLocalMatrix) {
448b67b8e6052bf5567eb3f9726dda99a6b260dfb05reed@google.com        newMatrix.preConcat(*rec.fLocalMatrix);
449b67b8e6052bf5567eb3f9726dda99a6b260dfb05reed@google.com    }
450a8d95f899bf3fe404d3cd5c357531ff852c15b29senorblanco@chromium.org    // This (1,1) translation is due to WebKit's 1 based coordinates for the noise
451a8d95f899bf3fe404d3cd5c357531ff852c15b29senorblanco@chromium.org    // (as opposed to 0 based, usually). The same adjustment is in the setData() function.
452ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco    fMatrix.setTranslate(-newMatrix.getTranslateX() + SK_Scalar1, -newMatrix.getTranslateY() + SK_Scalar1);
453385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    fPaintingData = new PaintingData(shader.fTileSize, shader.fSeed, shader.fBaseFrequencyX,
454385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary                                     shader.fBaseFrequencyY, newMatrix);
455ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco}
456ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco
457385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanarySkPerlinNoiseShader::PerlinNoiseShaderContext::~PerlinNoiseShaderContext() { delete fPaintingData; }
458e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
45987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgvoid SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan(
46087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        int x, int y, SkPMColor result[], int count) {
461e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
462e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    StitchData stitchData;
463e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    for (int i = 0; i < count; ++i) {
464e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        result[i] = shade(point, stitchData);
465e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        point.fX += SK_Scalar1;
466e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
467e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}
468e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
469e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com/////////////////////////////////////////////////////////////////////
470e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
471344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org#if SK_SUPPORT_GPU
472e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
47364c4728c70001ed074fecf5c4e083781987b12e9egdanielclass GrGLPerlinNoise : public GrGLSLFragmentProcessor {
4744775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.compublic:
4759cdb9920fcad286ecf7875ea19902022b644fbdcrobertphillips    void emitCode(EmitArgs&) override;
476e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
477bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips    static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*);
4784775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com
479b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyixprotected:
480018fb62d12d1febf121fe265da5b6117b86a6541egdaniel    void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
481b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyix
482f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblancoprivate:
483018fb62d12d1febf121fe265da5b6117b86a6541egdaniel    GrGLSLProgramDataManager::UniformHandle fStitchDataUni;
484018fb62d12d1febf121fe265da5b6117b86a6541egdaniel    GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
485e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
48664c4728c70001ed074fecf5c4e083781987b12e9egdaniel    typedef GrGLSLFragmentProcessor INHERITED;
487e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com};
488e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
489e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com/////////////////////////////////////////////////////////////////////
490e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
491b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GrPerlinNoiseEffect : public GrFragmentProcessor {
492e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.compublic:
4934a339529612a43871d021877e58698e067d6c4cdbsalomon    static GrFragmentProcessor* Create(SkPerlinNoiseShader::Type type,
494b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                       int numOctaves, bool stitchTiles,
495b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                       SkPerlinNoiseShader::PaintingData* paintingData,
496b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                       GrTexture* permutationsTexture, GrTexture* noiseTexture,
497c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon                                       const SkMatrix& matrix) {
4984a339529612a43871d021877e58698e067d6c4cdbsalomon        return new GrPerlinNoiseEffect(type, numOctaves, stitchTiles, paintingData,
499c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon                                       permutationsTexture, noiseTexture, matrix);
500e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
501e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
502385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    virtual ~GrPerlinNoiseEffect() { delete fPaintingData; }
503e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
50436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    const char* name() const override { return "PerlinNoise"; }
505eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
506ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco    const SkPerlinNoiseShader::StitchData& stitchData() const { return fPaintingData->fStitchDataInit; }
507e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
508f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco    SkPerlinNoiseShader::Type type() const { return fType; }
509f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco    bool stitchTiles() const { return fStitchTiles; }
510ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco    const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
511f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco    int numOctaves() const { return fNumOctaves; }
512f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco    const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
513f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco
514e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comprivate:
51557d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
516bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips        return new GrGLPerlinNoise;
517b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyix    }
518b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyix
51957d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel    virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps,
52057d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel                                       GrProcessorKeyBuilder* b) const override {
5214b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix        GrGLPerlinNoise::GenKey(*this, caps, b);
5224b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix    }
5234b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix
52436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    bool onIsEqual(const GrFragmentProcessor& sBase) const override {
52549586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt        const GrPerlinNoiseEffect& s = sBase.cast<GrPerlinNoiseEffect>();
526f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco        return fType == s.fType &&
527ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco               fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency &&
528f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco               fNumOctaves == s.fNumOctaves &&
529f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco               fStitchTiles == s.fStitchTiles &&
530ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco               fPaintingData->fStitchDataInit == s.fPaintingData->fStitchDataInit;
531e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
532e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
53336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
534605dd0fbce9dbb2a0d3313e13e161f2bd54870d7egdaniel        inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput);
5351a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel    }
5361a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel
5374a339529612a43871d021877e58698e067d6c4cdbsalomon    GrPerlinNoiseEffect(SkPerlinNoiseShader::Type type,
538e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                        int numOctaves, bool stitchTiles,
539ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco                        SkPerlinNoiseShader::PaintingData* paintingData,
540e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com                        GrTexture* permutationsTexture, GrTexture* noiseTexture,
541c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon                        const SkMatrix& matrix)
542f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco      : fType(type)
543f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco      , fNumOctaves(numOctaves)
544f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco      , fStitchTiles(stitchTiles)
5454775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com      , fPermutationsAccess(permutationsTexture)
546e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com      , fNoiseAccess(noiseTexture)
547ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco      , fPaintingData(paintingData) {
548eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt        this->initClassID<GrPerlinNoiseEffect>();
549e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        this->addTextureAccess(&fPermutationsAccess);
550e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        this->addTextureAccess(&fNoiseAccess);
551ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco        fCoordTransform.reset(kLocal_GrCoordSet, matrix);
552f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco        this->addCoordTransform(&fCoordTransform);
553e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
554e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
555b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
556e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
557f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco    SkPerlinNoiseShader::Type       fType;
558f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco    GrCoordTransform                fCoordTransform;
559f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco    int                             fNumOctaves;
560f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco    bool                            fStitchTiles;
561e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    GrTextureAccess                 fPermutationsAccess;
562e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    GrTextureAccess                 fNoiseAccess;
563ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco    SkPerlinNoiseShader::PaintingData *fPaintingData;
564e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
5654775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.comprivate:
566b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    typedef GrFragmentProcessor INHERITED;
567e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com};
568e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
569e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com/////////////////////////////////////////////////////////////////////
570b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrPerlinNoiseEffect);
571e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
572c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomonconst GrFragmentProcessor* GrPerlinNoiseEffect::TestCreate(GrProcessorTestData* d) {
5730067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt    int      numOctaves = d->fRandom->nextRangeU(2, 10);
5740067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt    bool     stitchTiles = d->fRandom->nextBool();
5750067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt    SkScalar seed = SkIntToScalar(d->fRandom->nextU());
5760067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt    SkISize  tileSize = SkISize::Make(d->fRandom->nextRangeU(4, 4096),
5770067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt                                      d->fRandom->nextRangeU(4, 4096));
5780067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt    SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
5790067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt                                                          0.99f);
5800067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt    SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
5810067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt                                                          0.99f);
5820067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt
5836d2a203117015b4da13dbc5f627646df69d92653bsalomon    SkAutoTUnref<SkShader> shader(d->fRandom->nextBool() ?
584e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        SkPerlinNoiseShader::CreateFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves, seed,
58596fcdcc219d2a0d3579719b84b28bede76efba64halcanary                                                stitchTiles ? &tileSize : nullptr) :
5869fbbcca1c958e6df2cff24d3ccdb7ebd89b8486bcommit-bot@chromium.org        SkPerlinNoiseShader::CreateTurbulence(baseFrequencyX, baseFrequencyY, numOctaves, seed,
5876d2a203117015b4da13dbc5f627646df69d92653bsalomon                                             stitchTiles ? &tileSize : nullptr));
588e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
589c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon    return shader->asFragmentProcessor(d->fContext,
590c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon                                       GrTest::TestMatrix(d->fRandom), nullptr,
5914a339529612a43871d021877e58698e067d6c4cdbsalomon                                       kNone_SkFilterQuality);
592e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}
5934775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com
5947c157a988845fb00f9024d6db6dda142c3458033wangyixvoid GrGLPerlinNoise::emitCode(EmitArgs& args) {
595bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips    const GrPerlinNoiseEffect& pne = args.fFp.cast<GrPerlinNoiseEffect>();
596bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips
5978528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
5987ea439b2203855db97330b25945b87dd4b170b8begdaniel    GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
5994ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel    SkString vCoords = fragBuilder->ensureFSCoords2D(args.fCoords, 0);
600e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
6015e58ceea8569f0d90ff7e3daf5de2def50407212cdalton    fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
6027ea439b2203855db97330b25945b87dd4b170b8begdaniel                                                   kVec2f_GrSLType, kDefault_GrSLPrecision,
6037ea439b2203855db97330b25945b87dd4b170b8begdaniel                                                   "baseFrequency");
6047ea439b2203855db97330b25945b87dd4b170b8begdaniel    const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
605e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
60696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const char* stitchDataUni = nullptr;
607bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips    if (pne.stitchTiles()) {
6085e58ceea8569f0d90ff7e3daf5de2def50407212cdalton        fStitchDataUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
6097ea439b2203855db97330b25945b87dd4b170b8begdaniel                                                    kVec2f_GrSLType, kDefault_GrSLPrecision,
6107ea439b2203855db97330b25945b87dd4b170b8begdaniel                                                    "stitchData");
6117ea439b2203855db97330b25945b87dd4b170b8begdaniel        stitchDataUni = uniformHandler->getUniformCStr(fStitchDataUni);
612e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
613e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
614d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8
615d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    const char* chanCoordR  = "0.125";
616d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    const char* chanCoordG  = "0.375";
617d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    const char* chanCoordB  = "0.625";
618d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    const char* chanCoordA  = "0.875";
619d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    const char* chanCoord   = "chanCoord";
620e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    const char* stitchData  = "stitchData";
621e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    const char* ratio       = "ratio";
622e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    const char* noiseVec    = "noiseVec";
623e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    const char* noiseSmooth = "noiseSmooth";
624ce6a354e121915c2925e545e7df2929492d69d50senorblanco    const char* floorVal    = "floorVal";
625e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    const char* fractVal    = "fractVal";
626e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    const char* uv          = "uv";
627e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    const char* ab          = "ab";
628e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    const char* latticeIdx  = "latticeIdx";
629ce6a354e121915c2925e545e7df2929492d69d50senorblanco    const char* bcoords     = "bcoords";
630e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    const char* lattice     = "lattice";
631e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    const char* inc8bit     = "0.00390625";  // 1.0 / 256.0
632e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a
633e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // [-1,1] vector and perform a dot product between that vector and the provided vector.
634e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    const char* dotLattice  = "dot(((%s.ga + %s.rb * vec2(%s)) * vec2(2.0) - vec2(1.0)), %s);";
635e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
636d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    // Add noise function
6370d3f061262a53b775f0a92b0abf8a4a846290d65egdaniel    static const GrGLSLShaderVar gPerlinNoiseArgs[] =  {
6380d3f061262a53b775f0a92b0abf8a4a846290d65egdaniel        GrGLSLShaderVar(chanCoord, kFloat_GrSLType),
6390d3f061262a53b775f0a92b0abf8a4a846290d65egdaniel        GrGLSLShaderVar(noiseVec, kVec2f_GrSLType)
640d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    };
641e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
6420d3f061262a53b775f0a92b0abf8a4a846290d65egdaniel    static const GrGLSLShaderVar gPerlinNoiseStitchArgs[] =  {
6430d3f061262a53b775f0a92b0abf8a4a846290d65egdaniel        GrGLSLShaderVar(chanCoord, kFloat_GrSLType),
6440d3f061262a53b775f0a92b0abf8a4a846290d65egdaniel        GrGLSLShaderVar(noiseVec, kVec2f_GrSLType),
6450d3f061262a53b775f0a92b0abf8a4a846290d65egdaniel        GrGLSLShaderVar(stitchData, kVec2f_GrSLType)
646d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    };
647e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
648d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    SkString noiseCode;
649e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
650ce6a354e121915c2925e545e7df2929492d69d50senorblanco    noiseCode.appendf("\tvec4 %s;\n", floorVal);
651ce6a354e121915c2925e545e7df2929492d69d50senorblanco    noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec);
652ce6a354e121915c2925e545e7df2929492d69d50senorblanco    noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal);
653ce6a354e121915c2925e545e7df2929492d69d50senorblanco    noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec);
654e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
655e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // smooth curve : t * t * (3 - 2 * t)
656ce6a354e121915c2925e545e7df2929492d69d50senorblanco    noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);",
657ce6a354e121915c2925e545e7df2929492d69d50senorblanco        noiseSmooth, fractVal, fractVal, fractVal);
658e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
659e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // Adjust frequencies if we're stitching tiles
660bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips    if (pne.stitchTiles()) {
6619839320ae17ab1c2182dc144db5ba94caa1bde56commit-bot@chromium.org        noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }",
6624ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                          floorVal, stitchData, floorVal, stitchData);
6639839320ae17ab1c2182dc144db5ba94caa1bde56commit-bot@chromium.org        noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }",
6644ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                          floorVal, stitchData, floorVal, stitchData);
665ce6a354e121915c2925e545e7df2929492d69d50senorblanco        noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }",
6664ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                          floorVal, stitchData, floorVal, stitchData);
667ce6a354e121915c2925e545e7df2929492d69d50senorblanco        noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }",
6684ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                          floorVal, stitchData, floorVal, stitchData);
669e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
670e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
671e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // Get texture coordinates and normalize
672ce6a354e121915c2925e545e7df2929492d69d50senorblanco    noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / vec4(256.0));\n",
6734ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                      floorVal, floorVal);
674e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
675e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // Get permutation for x
676e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    {
677e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        SkString xCoords("");
678ce6a354e121915c2925e545e7df2929492d69d50senorblanco        xCoords.appendf("vec2(%s.x, 0.5)", floorVal);
679e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
680d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com        noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
6814ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel        fragBuilder->appendTextureLookup(&noiseCode, args.fSamplers[0], xCoords.c_str(),
6824ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                                         kVec2f_GrSLType);
683d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com        noiseCode.append(".r;");
684e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
685e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
686e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // Get permutation for x + 1
687e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    {
688e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        SkString xCoords("");
689ce6a354e121915c2925e545e7df2929492d69d50senorblanco        xCoords.appendf("vec2(%s.z, 0.5)", floorVal);
690e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
691d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com        noiseCode.appendf("\n\t%s.y = ", latticeIdx);
6924ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel        fragBuilder->appendTextureLookup(&noiseCode, args.fSamplers[0], xCoords.c_str(),
6934ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                                         kVec2f_GrSLType);
694d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com        noiseCode.append(".r;");
695e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
696e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
697344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org#if defined(SK_BUILD_FOR_ANDROID)
698344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org    // Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3).
699344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org    // The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit
700344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org    // value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725
701344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org    // (or 0.484368 here). The following rounding operation prevents these precision issues from
702344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org    // affecting the result of the noise by making sure that we only have multiples of 1/255.
703344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org    // (Note that 1/255 is about 0.003921569, which is the value used here).
704344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org    noiseCode.appendf("\n\t%s = floor(%s * vec2(255.0) + vec2(0.5)) * vec2(0.003921569);",
705344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org                      latticeIdx, latticeIdx);
706344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org#endif
707344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org
708e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // Get (x,y) coordinates with the permutated x
709ce6a354e121915c2925e545e7df2929492d69d50senorblanco    noiseCode.appendf("\n\tvec4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal);
710e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
711d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    noiseCode.appendf("\n\n\tvec2 %s;", uv);
712e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // Compute u, at offset (0,0)
713e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    {
714e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        SkString latticeCoords("");
715ce6a354e121915c2925e545e7df2929492d69d50senorblanco        latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord);
716d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com        noiseCode.appendf("\n\tvec4 %s = ", lattice);
7174ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel        fragBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
7184ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                                         kVec2f_GrSLType);
719d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com        noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
720d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com        noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
721e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
722e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
723d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal);
724e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // Compute v, at offset (-1,0)
725e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    {
726e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        SkString latticeCoords("");
727ce6a354e121915c2925e545e7df2929492d69d50senorblanco        latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord);
728344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org        noiseCode.append("\n\tlattice = ");
7294ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel        fragBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
7304ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                                         kVec2f_GrSLType);
731d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com        noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
732d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com        noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
733e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
734e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
735e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // Compute 'a' as a linear interpolation of 'u' and 'v'
736d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    noiseCode.appendf("\n\tvec2 %s;", ab);
737d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
738e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
739d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal);
740e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // Compute v, at offset (-1,-1)
741e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    {
742e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        SkString latticeCoords("");
743ce6a354e121915c2925e545e7df2929492d69d50senorblanco        latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord);
744344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org        noiseCode.append("\n\tlattice = ");
7454ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel        fragBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
7464ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                                         kVec2f_GrSLType);
747d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com        noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
748d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com        noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
749e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
750e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
751d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    noiseCode.appendf("\n\t%s.x += 1.0;", fractVal);
752e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // Compute u, at offset (0,-1)
753e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    {
754e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        SkString latticeCoords("");
755ce6a354e121915c2925e545e7df2929492d69d50senorblanco        latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord);
756344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org        noiseCode.append("\n\tlattice = ");
7574ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel        fragBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
7584ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                                         kVec2f_GrSLType);
759d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com        noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
760d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com        noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
761e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
762e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
763e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // Compute 'b' as a linear interpolation of 'u' and 'v'
764d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
765e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // Compute the noise as a linear interpolation of 'a' and 'b'
766d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth);
767d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com
768d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    SkString noiseFuncName;
769bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips    if (pne.stitchTiles()) {
7704ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel        fragBuilder->emitFunction(kFloat_GrSLType,
7714ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                                  "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs),
7724ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                                  gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName);
773d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    } else {
7744ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel        fragBuilder->emitFunction(kFloat_GrSLType,
7754ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                                  "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs),
7764ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                                  gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName);
777d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    }
778e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
779d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    // There are rounding errors if the floor operation is not performed here
7804ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel    fragBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;",
7814ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                             noiseVec, vCoords.c_str(), baseFrequencyUni);
782e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
783d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    // Clear the color accumulator
7844ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel    fragBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", args.fOutputColor);
785e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
786bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips    if (pne.stitchTiles()) {
787d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com        // Set up TurbulenceInitial stitch values.
788bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips        fragBuilder->codeAppendf("vec2 %s = %s;", stitchData, stitchDataUni);
789e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
790e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
791bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips    fragBuilder->codeAppendf("float %s = 1.0;", ratio);
792d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com
793d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    // Loop over all octaves
794bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips    fragBuilder->codeAppendf("for (int octave = 0; octave < %d; ++octave) {", pne.numOctaves());
795d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com
796bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips    fragBuilder->codeAppendf("%s += ", args.fOutputColor);
797bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips    if (pne.type() != SkPerlinNoiseShader::kFractalNoise_Type) {
7984ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel        fragBuilder->codeAppend("abs(");
799d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    }
800bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips    if (pne.stitchTiles()) {
8014ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel        fragBuilder->codeAppendf(
802d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com            "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s),"
803d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com                 "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))",
804d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com            noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData,
805d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com            noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData,
806d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com            noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData,
807d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com            noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData);
808d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    } else {
8094ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel        fragBuilder->codeAppendf(
810d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com            "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s),"
811d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com                 "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))",
812d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com            noiseFuncName.c_str(), chanCoordR, noiseVec,
813d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com            noiseFuncName.c_str(), chanCoordG, noiseVec,
814d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com            noiseFuncName.c_str(), chanCoordB, noiseVec,
815d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com            noiseFuncName.c_str(), chanCoordA, noiseVec);
816d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    }
817bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips    if (pne.type() != SkPerlinNoiseShader::kFractalNoise_Type) {
8184ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel        fragBuilder->codeAppendf(")"); // end of "abs("
819d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    }
8204ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel    fragBuilder->codeAppendf(" * %s;", ratio);
821d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com
8224ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel    fragBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec);
8234ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel    fragBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio);
824d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com
825bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips    if (pne.stitchTiles()) {
8264ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel        fragBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData);
827d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com    }
8284ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel    fragBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves
829e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
830bf536af15f4c176d3bef65b77b7592718bfd9068robertphillips    if (pne.type() == SkPerlinNoiseShader::kFractalNoise_Type) {
831e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
832e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        // by fractalNoise and (turbulenceFunctionResult) by turbulence.
8334ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel        fragBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);",
8344ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                                 args.fOutputColor,args.fOutputColor);
835e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
836e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
837e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // Clamp values
8384ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel    fragBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
839e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
840e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // Pre-multiply the result
8414ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel    fragBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
8424ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                             args.fOutputColor, args.fOutputColor,
8434ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                             args.fOutputColor, args.fOutputColor);
844e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}
845e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
846cfc18867d982119d9dc2888bf09f1093012daaddjvanverthvoid GrGLPerlinNoise::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
847b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                             GrProcessorKeyBuilder* b) {
848b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    const GrPerlinNoiseEffect& turbulence = processor.cast<GrPerlinNoiseEffect>();
849e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
85063e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon    uint32_t key = turbulence.numOctaves();
851e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
852e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    key = key << 3; // Make room for next 3 bits
853e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
854e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    switch (turbulence.type()) {
855e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        case SkPerlinNoiseShader::kFractalNoise_Type:
856e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            key |= 0x1;
857e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            break;
858e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        case SkPerlinNoiseShader::kTurbulence_Type:
859e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            key |= 0x2;
860e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            break;
861e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        default:
862e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            // leave key at 0
863e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            break;
864e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
865e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
866e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    if (turbulence.stitchTiles()) {
867e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        key |= 0x4; // Flip the 3rd bit if tile stitching is on
868e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
869e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
87063e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon    b->add32(key);
871e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}
872e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
873018fb62d12d1febf121fe265da5b6117b86a6541egdanielvoid GrGLPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman,
874018fb62d12d1febf121fe265da5b6117b86a6541egdaniel                                const GrProcessor& processor) {
875b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyix    INHERITED::onSetData(pdman, processor);
876f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco
877b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    const GrPerlinNoiseEffect& turbulence = processor.cast<GrPerlinNoiseEffect>();
878e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
879e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    const SkVector& baseFrequency = turbulence.baseFrequency();
8807510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
881e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
8824775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com    if (turbulence.stitchTiles()) {
8834775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com        const SkPerlinNoiseShader::StitchData& stitchData = turbulence.stitchData();
8847510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen        pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth),
8859839320ae17ab1c2182dc144db5ba94caa1bde56commit-bot@chromium.org                                   SkIntToScalar(stitchData.fHeight));
8864775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com    }
8874775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com}
8884775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com
889e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com/////////////////////////////////////////////////////////////////////
890c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomonconst GrFragmentProcessor* SkPerlinNoiseShader::asFragmentProcessor(
891c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon                                                    GrContext* context,
892c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon                                                    const SkMatrix& viewM,
893c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon                                                    const SkMatrix* externalLocalMatrix,
8944a339529612a43871d021877e58698e067d6c4cdbsalomon                                                    SkFilterQuality) const {
89549f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(context);
8963f3b3d003527861dc0bd89733857576408906431mtklein
89796fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org    SkMatrix localMatrix = this->getLocalMatrix();
89896fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org    if (externalLocalMatrix) {
89996fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org        localMatrix.preConcat(*externalLocalMatrix);
90096fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org    }
90196fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org
9025531d51ce7426bdae7563547326fcf0bf926a083joshualitt    SkMatrix matrix = viewM;
903ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco    matrix.preConcat(localMatrix);
904ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco
905c2a0ea6418988d4bcc0719f99b1a110cecd08679commit-bot@chromium.org    if (0 == fNumOctaves) {
906c2a0ea6418988d4bcc0719f99b1a110cecd08679commit-bot@chromium.org        if (kFractalNoise_Type == fType) {
907c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon            // Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2)
908c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon            SkAutoTUnref<const GrFragmentProcessor> inner(
909c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon                GrConstColorProcessor::Create(0x80404040,
910c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon                                              GrConstColorProcessor::kModulateRGBA_InputMode));
911f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon            return GrFragmentProcessor::MulOutputByInputAlpha(inner);
912cff10b21a9934afc540d121b493b204335829589reed        }
913c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon        // Emit zero.
914c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon        return GrConstColorProcessor::Create(0x0, GrConstColorProcessor::kIgnore_InputMode);
915c2a0ea6418988d4bcc0719f99b1a110cecd08679commit-bot@chromium.org    }
916c2a0ea6418988d4bcc0719f99b1a110cecd08679commit-bot@chromium.org
917e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    // Either we don't stitch tiles, either we have a valid tile size
918e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
919e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
920b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    SkPerlinNoiseShader::PaintingData* paintingData =
921385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            new PaintingData(fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY, matrix);
922bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon    SkAutoTUnref<GrTexture> permutationsTexture(
923afa95e270c64c9777647b6c58b796750ced57c39bsalomon        GrRefCachedBitmapTexture(context, paintingData->getPermutationsBitmap(),
924afa95e270c64c9777647b6c58b796750ced57c39bsalomon                                 GrTextureParams::ClampNoFilter()));
925bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon    SkAutoTUnref<GrTexture> noiseTexture(
926afa95e270c64c9777647b6c58b796750ced57c39bsalomon        GrRefCachedBitmapTexture(context, paintingData->getNoiseBitmap(),
927afa95e270c64c9777647b6c58b796750ced57c39bsalomon                                 GrTextureParams::ClampNoFilter()));
928ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco
9295531d51ce7426bdae7563547326fcf0bf926a083joshualitt    SkMatrix m = viewM;
930ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco    m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1);
931ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco    m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1);
93249f085dddff10473b6ebf832a974288300224e60bsalomon    if ((permutationsTexture) && (noiseTexture)) {
933c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon        SkAutoTUnref<GrFragmentProcessor> inner(
9344a339529612a43871d021877e58698e067d6c4cdbsalomon            GrPerlinNoiseEffect::Create(fType,
935c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon                                        fNumOctaves,
936c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon                                        fStitchTiles,
937c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon                                        paintingData,
938c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon                                        permutationsTexture, noiseTexture,
939c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon                                        m));
940f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon        return GrFragmentProcessor::MulOutputByInputAlpha(inner);
941c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon    }
942c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon    delete paintingData;
943c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomon    return nullptr;
944e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}
945e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
946e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#endif
947e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
9480f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
949e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comvoid SkPerlinNoiseShader::toString(SkString* str) const {
950e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    str->append("SkPerlinNoiseShader: (");
951e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
952e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    str->append("type: ");
953e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    switch (fType) {
954e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        case kFractalNoise_Type:
955e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            str->append("\"fractal noise\"");
956e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            break;
957e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        case kTurbulence_Type:
958e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            str->append("\"turbulence\"");
959e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            break;
960e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com        default:
961e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            str->append("\"unknown\"");
962e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com            break;
963e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    }
964e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    str->append(" base frequency: (");
965e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    str->appendScalar(fBaseFrequencyX);
966e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    str->append(", ");
967e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    str->appendScalar(fBaseFrequencyY);
968e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    str->append(") number of octaves: ");
969e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    str->appendS32(fNumOctaves);
970e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    str->append(" seed: ");
971e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    str->appendScalar(fSeed);
972e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    str->append(" stitch tiles: ");
973e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    str->append(fStitchTiles ? "true " : "false ");
974e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
975e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    this->INHERITED::toString(str);
976e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com
977e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com    str->append(")");
978e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}
979e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#endif
980