• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2013 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkPerlinNoiseShader.h"
9 #include "SkColorFilter.h"
10 #include "SkReadBuffer.h"
11 #include "SkWriteBuffer.h"
12 #include "SkShader.h"
13 #include "SkUnPreMultiply.h"
14 #include "SkString.h"
15 
16 #if SK_SUPPORT_GPU
17 #include "GrContext.h"
18 #include "GrCoordTransform.h"
19 #include "GrInvariantOutput.h"
20 #include "SkGr.h"
21 #include "effects/GrConstColorProcessor.h"
22 #include "glsl/GrGLSLFragmentProcessor.h"
23 #include "glsl/GrGLSLFragmentShaderBuilder.h"
24 #include "glsl/GrGLSLProgramDataManager.h"
25 #include "glsl/GrGLSLUniformHandler.h"
26 #endif
27 
28 static const int kBlockSize = 256;
29 static const int kBlockMask = kBlockSize - 1;
30 static const int kPerlinNoise = 4096;
31 static const int kRandMaximum = SK_MaxS32; // 2**31 - 1
32 
33 namespace {
34 
35 // noiseValue is the color component's value (or color)
36 // limitValue is the maximum perlin noise array index value allowed
37 // newValue is the current noise dimension (either width or height)
checkNoise(int noiseValue,int limitValue,int newValue)38 inline int checkNoise(int noiseValue, int limitValue, int newValue) {
39     // If the noise value would bring us out of bounds of the current noise array while we are
40     // stiching noise tiles together, wrap the noise around the current dimension of the noise to
41     // stay within the array bounds in a continuous fashion (so that tiling lines are not visible)
42     if (noiseValue >= limitValue) {
43         noiseValue -= newValue;
44     }
45     return noiseValue;
46 }
47 
smoothCurve(SkScalar t)48 inline SkScalar smoothCurve(SkScalar t) {
49     static const SkScalar SK_Scalar3 = 3.0f;
50 
51     // returns t * t * (3 - 2 * t)
52     return SkScalarMul(SkScalarSquare(t), SK_Scalar3 - 2 * t);
53 }
54 
55 } // end namespace
56 
57 struct SkPerlinNoiseShader::StitchData {
StitchDataSkPerlinNoiseShader::StitchData58     StitchData()
59       : fWidth(0)
60       , fWrapX(0)
61       , fHeight(0)
62       , fWrapY(0)
63     {}
64 
operator ==SkPerlinNoiseShader::StitchData65     bool operator==(const StitchData& other) const {
66         return fWidth == other.fWidth &&
67                fWrapX == other.fWrapX &&
68                fHeight == other.fHeight &&
69                fWrapY == other.fWrapY;
70     }
71 
72     int fWidth; // How much to subtract to wrap for stitching.
73     int fWrapX; // Minimum value to wrap.
74     int fHeight;
75     int fWrapY;
76 };
77 
78 struct SkPerlinNoiseShader::PaintingData {
PaintingDataSkPerlinNoiseShader::PaintingData79     PaintingData(const SkISize& tileSize, SkScalar seed,
80                  SkScalar baseFrequencyX, SkScalar baseFrequencyY,
81                  const SkMatrix& matrix)
82     {
83         SkVector vec[2] = {
84             { SkScalarInvert(baseFrequencyX),   SkScalarInvert(baseFrequencyY)  },
85             { SkIntToScalar(tileSize.fWidth),   SkIntToScalar(tileSize.fHeight) },
86         };
87         matrix.mapVectors(vec, 2);
88 
89         fBaseFrequency.set(SkScalarInvert(vec[0].fX), SkScalarInvert(vec[0].fY));
90         fTileSize.set(SkScalarRoundToInt(vec[1].fX), SkScalarRoundToInt(vec[1].fY));
91         this->init(seed);
92         if (!fTileSize.isEmpty()) {
93             this->stitch();
94         }
95 
96 #if SK_SUPPORT_GPU
97         fPermutationsBitmap.setInfo(SkImageInfo::MakeA8(kBlockSize, 1));
98         fPermutationsBitmap.setPixels(fLatticeSelector);
99 
100         fNoiseBitmap.setInfo(SkImageInfo::MakeN32Premul(kBlockSize, 4));
101         fNoiseBitmap.setPixels(fNoise[0][0]);
102 #endif
103     }
104 
105     int         fSeed;
106     uint8_t     fLatticeSelector[kBlockSize];
107     uint16_t    fNoise[4][kBlockSize][2];
108     SkPoint     fGradient[4][kBlockSize];
109     SkISize     fTileSize;
110     SkVector    fBaseFrequency;
111     StitchData  fStitchDataInit;
112 
113 private:
114 
115 #if SK_SUPPORT_GPU
116     SkBitmap   fPermutationsBitmap;
117     SkBitmap   fNoiseBitmap;
118 #endif
119 
randomSkPerlinNoiseShader::PaintingData120     inline int random()  {
121         static const int gRandAmplitude = 16807; // 7**5; primitive root of m
122         static const int gRandQ = 127773; // m / a
123         static const int gRandR = 2836; // m % a
124 
125         int result = gRandAmplitude * (fSeed % gRandQ) - gRandR * (fSeed / gRandQ);
126         if (result <= 0)
127             result += kRandMaximum;
128         fSeed = result;
129         return result;
130     }
131 
132     // Only called once. Could be part of the constructor.
initSkPerlinNoiseShader::PaintingData133     void init(SkScalar seed)
134     {
135         static const SkScalar gInvBlockSizef = SkScalarInvert(SkIntToScalar(kBlockSize));
136 
137         // According to the SVG spec, we must truncate (not round) the seed value.
138         fSeed = SkScalarTruncToInt(seed);
139         // The seed value clamp to the range [1, kRandMaximum - 1].
140         if (fSeed <= 0) {
141             fSeed = -(fSeed % (kRandMaximum - 1)) + 1;
142         }
143         if (fSeed > kRandMaximum - 1) {
144             fSeed = kRandMaximum - 1;
145         }
146         for (int channel = 0; channel < 4; ++channel) {
147             for (int i = 0; i < kBlockSize; ++i) {
148                 fLatticeSelector[i] = i;
149                 fNoise[channel][i][0] = (random() % (2 * kBlockSize));
150                 fNoise[channel][i][1] = (random() % (2 * kBlockSize));
151             }
152         }
153         for (int i = kBlockSize - 1; i > 0; --i) {
154             int k = fLatticeSelector[i];
155             int j = random() % kBlockSize;
156             SkASSERT(j >= 0);
157             SkASSERT(j < kBlockSize);
158             fLatticeSelector[i] = fLatticeSelector[j];
159             fLatticeSelector[j] = k;
160         }
161 
162         // Perform the permutations now
163         {
164             // Copy noise data
165             uint16_t noise[4][kBlockSize][2];
166             for (int i = 0; i < kBlockSize; ++i) {
167                 for (int channel = 0; channel < 4; ++channel) {
168                     for (int j = 0; j < 2; ++j) {
169                         noise[channel][i][j] = fNoise[channel][i][j];
170                     }
171                 }
172             }
173             // Do permutations on noise data
174             for (int i = 0; i < kBlockSize; ++i) {
175                 for (int channel = 0; channel < 4; ++channel) {
176                     for (int j = 0; j < 2; ++j) {
177                         fNoise[channel][i][j] = noise[channel][fLatticeSelector[i]][j];
178                     }
179                 }
180             }
181         }
182 
183         // Half of the largest possible value for 16 bit unsigned int
184         static const SkScalar gHalfMax16bits = 32767.5f;
185 
186         // Compute gradients from permutated noise data
187         for (int channel = 0; channel < 4; ++channel) {
188             for (int i = 0; i < kBlockSize; ++i) {
189                 fGradient[channel][i] = SkPoint::Make(
190                     SkScalarMul(SkIntToScalar(fNoise[channel][i][0] - kBlockSize),
191                                 gInvBlockSizef),
192                     SkScalarMul(SkIntToScalar(fNoise[channel][i][1] - kBlockSize),
193                                 gInvBlockSizef));
194                 fGradient[channel][i].normalize();
195                 // Put the normalized gradient back into the noise data
196                 fNoise[channel][i][0] = SkScalarRoundToInt(SkScalarMul(
197                     fGradient[channel][i].fX + SK_Scalar1, gHalfMax16bits));
198                 fNoise[channel][i][1] = SkScalarRoundToInt(SkScalarMul(
199                     fGradient[channel][i].fY + SK_Scalar1, gHalfMax16bits));
200             }
201         }
202     }
203 
204     // Only called once. Could be part of the constructor.
stitchSkPerlinNoiseShader::PaintingData205     void stitch() {
206         SkScalar tileWidth  = SkIntToScalar(fTileSize.width());
207         SkScalar tileHeight = SkIntToScalar(fTileSize.height());
208         SkASSERT(tileWidth > 0 && tileHeight > 0);
209         // When stitching tiled turbulence, the frequencies must be adjusted
210         // so that the tile borders will be continuous.
211         if (fBaseFrequency.fX) {
212             SkScalar lowFrequencx =
213                 SkScalarFloorToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
214             SkScalar highFrequencx =
215                 SkScalarCeilToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
216             // BaseFrequency should be non-negative according to the standard.
217             if (fBaseFrequency.fX / lowFrequencx < highFrequencx / fBaseFrequency.fX) {
218                 fBaseFrequency.fX = lowFrequencx;
219             } else {
220                 fBaseFrequency.fX = highFrequencx;
221             }
222         }
223         if (fBaseFrequency.fY) {
224             SkScalar lowFrequency =
225                 SkScalarFloorToScalar(tileHeight * fBaseFrequency.fY) / tileHeight;
226             SkScalar highFrequency =
227                 SkScalarCeilToScalar(tileHeight * fBaseFrequency.fY) / tileHeight;
228             if (fBaseFrequency.fY / lowFrequency < highFrequency / fBaseFrequency.fY) {
229                 fBaseFrequency.fY = lowFrequency;
230             } else {
231                 fBaseFrequency.fY = highFrequency;
232             }
233         }
234         // Set up TurbulenceInitial stitch values.
235         fStitchDataInit.fWidth  =
236             SkScalarRoundToInt(tileWidth * fBaseFrequency.fX);
237         fStitchDataInit.fWrapX  = kPerlinNoise + fStitchDataInit.fWidth;
238         fStitchDataInit.fHeight =
239             SkScalarRoundToInt(tileHeight * fBaseFrequency.fY);
240         fStitchDataInit.fWrapY  = kPerlinNoise + fStitchDataInit.fHeight;
241     }
242 
243 public:
244 
245 #if SK_SUPPORT_GPU
getPermutationsBitmapSkPerlinNoiseShader::PaintingData246     const SkBitmap& getPermutationsBitmap() const { return fPermutationsBitmap; }
247 
getNoiseBitmapSkPerlinNoiseShader::PaintingData248     const SkBitmap& getNoiseBitmap() const { return fNoiseBitmap; }
249 #endif
250 };
251 
CreateFractalNoise(SkScalar baseFrequencyX,SkScalar baseFrequencyY,int numOctaves,SkScalar seed,const SkISize * tileSize)252 SkShader* SkPerlinNoiseShader::CreateFractalNoise(SkScalar baseFrequencyX, SkScalar baseFrequencyY,
253                                                   int numOctaves, SkScalar seed,
254                                                   const SkISize* tileSize) {
255     return new SkPerlinNoiseShader(kFractalNoise_Type, baseFrequencyX, baseFrequencyY, numOctaves,
256                                    seed, tileSize);
257 }
258 
CreateTurbulence(SkScalar baseFrequencyX,SkScalar baseFrequencyY,int numOctaves,SkScalar seed,const SkISize * tileSize)259 SkShader* SkPerlinNoiseShader::CreateTurbulence(SkScalar baseFrequencyX, SkScalar baseFrequencyY,
260                                               int numOctaves, SkScalar seed,
261                                               const SkISize* tileSize) {
262     return new SkPerlinNoiseShader(kTurbulence_Type, baseFrequencyX, baseFrequencyY, numOctaves,
263                                    seed, tileSize);
264 }
265 
SkPerlinNoiseShader(SkPerlinNoiseShader::Type type,SkScalar baseFrequencyX,SkScalar baseFrequencyY,int numOctaves,SkScalar seed,const SkISize * tileSize)266 SkPerlinNoiseShader::SkPerlinNoiseShader(SkPerlinNoiseShader::Type type,
267                                          SkScalar baseFrequencyX,
268                                          SkScalar baseFrequencyY,
269                                          int numOctaves,
270                                          SkScalar seed,
271                                          const SkISize* tileSize)
272   : fType(type)
273   , fBaseFrequencyX(baseFrequencyX)
274   , fBaseFrequencyY(baseFrequencyY)
275   , fNumOctaves(numOctaves > 255 ? 255 : numOctaves/*[0,255] octaves allowed*/)
276   , fSeed(seed)
277   , fTileSize(nullptr == tileSize ? SkISize::Make(0, 0) : *tileSize)
278   , fStitchTiles(!fTileSize.isEmpty())
279 {
280     SkASSERT(numOctaves >= 0 && numOctaves < 256);
281 }
282 
~SkPerlinNoiseShader()283 SkPerlinNoiseShader::~SkPerlinNoiseShader() {
284 }
285 
CreateProc(SkReadBuffer & buffer)286 SkFlattenable* SkPerlinNoiseShader::CreateProc(SkReadBuffer& buffer) {
287     Type type = (Type)buffer.readInt();
288     SkScalar freqX = buffer.readScalar();
289     SkScalar freqY = buffer.readScalar();
290     int octaves = buffer.readInt();
291     SkScalar seed = buffer.readScalar();
292     SkISize tileSize;
293     tileSize.fWidth = buffer.readInt();
294     tileSize.fHeight = buffer.readInt();
295 
296     switch (type) {
297         case kFractalNoise_Type:
298             return SkPerlinNoiseShader::CreateFractalNoise(freqX, freqY, octaves, seed, &tileSize);
299         case kTurbulence_Type:
300             return SkPerlinNoiseShader::CreateTubulence(freqX, freqY, octaves, seed, &tileSize);
301         default:
302             return nullptr;
303     }
304 }
305 
flatten(SkWriteBuffer & buffer) const306 void SkPerlinNoiseShader::flatten(SkWriteBuffer& buffer) const {
307     buffer.writeInt((int) fType);
308     buffer.writeScalar(fBaseFrequencyX);
309     buffer.writeScalar(fBaseFrequencyY);
310     buffer.writeInt(fNumOctaves);
311     buffer.writeScalar(fSeed);
312     buffer.writeInt(fTileSize.fWidth);
313     buffer.writeInt(fTileSize.fHeight);
314 }
315 
noise2D(int channel,const StitchData & stitchData,const SkPoint & noiseVector) const316 SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::noise2D(
317         int channel, const StitchData& stitchData, const SkPoint& noiseVector) const {
318     struct Noise {
319         int noisePositionIntegerValue;
320         int nextNoisePositionIntegerValue;
321         SkScalar noisePositionFractionValue;
322         Noise(SkScalar component)
323         {
324             SkScalar position = component + kPerlinNoise;
325             noisePositionIntegerValue = SkScalarFloorToInt(position);
326             noisePositionFractionValue = position - SkIntToScalar(noisePositionIntegerValue);
327             nextNoisePositionIntegerValue = noisePositionIntegerValue + 1;
328         }
329     };
330     Noise noiseX(noiseVector.x());
331     Noise noiseY(noiseVector.y());
332     SkScalar u, v;
333     const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader);
334     // If stitching, adjust lattice points accordingly.
335     if (perlinNoiseShader.fStitchTiles) {
336         noiseX.noisePositionIntegerValue =
337             checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
338         noiseY.noisePositionIntegerValue =
339             checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
340         noiseX.nextNoisePositionIntegerValue =
341             checkNoise(noiseX.nextNoisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
342         noiseY.nextNoisePositionIntegerValue =
343             checkNoise(noiseY.nextNoisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
344     }
345     noiseX.noisePositionIntegerValue &= kBlockMask;
346     noiseY.noisePositionIntegerValue &= kBlockMask;
347     noiseX.nextNoisePositionIntegerValue &= kBlockMask;
348     noiseY.nextNoisePositionIntegerValue &= kBlockMask;
349     int i =
350         fPaintingData->fLatticeSelector[noiseX.noisePositionIntegerValue];
351     int j =
352         fPaintingData->fLatticeSelector[noiseX.nextNoisePositionIntegerValue];
353     int b00 = (i + noiseY.noisePositionIntegerValue) & kBlockMask;
354     int b10 = (j + noiseY.noisePositionIntegerValue) & kBlockMask;
355     int b01 = (i + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
356     int b11 = (j + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
357     SkScalar sx = smoothCurve(noiseX.noisePositionFractionValue);
358     SkScalar sy = smoothCurve(noiseY.noisePositionFractionValue);
359     // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement
360     SkPoint fractionValue = SkPoint::Make(noiseX.noisePositionFractionValue,
361                                           noiseY.noisePositionFractionValue); // Offset (0,0)
362     u = fPaintingData->fGradient[channel][b00].dot(fractionValue);
363     fractionValue.fX -= SK_Scalar1; // Offset (-1,0)
364     v = fPaintingData->fGradient[channel][b10].dot(fractionValue);
365     SkScalar a = SkScalarInterp(u, v, sx);
366     fractionValue.fY -= SK_Scalar1; // Offset (-1,-1)
367     v = fPaintingData->fGradient[channel][b11].dot(fractionValue);
368     fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1)
369     u = fPaintingData->fGradient[channel][b01].dot(fractionValue);
370     SkScalar b = SkScalarInterp(u, v, sx);
371     return SkScalarInterp(a, b, sy);
372 }
373 
calculateTurbulenceValueForPoint(int channel,StitchData & stitchData,const SkPoint & point) const374 SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::calculateTurbulenceValueForPoint(
375         int channel, StitchData& stitchData, const SkPoint& point) const {
376     const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader);
377     if (perlinNoiseShader.fStitchTiles) {
378         // Set up TurbulenceInitial stitch values.
379         stitchData = fPaintingData->fStitchDataInit;
380     }
381     SkScalar turbulenceFunctionResult = 0;
382     SkPoint noiseVector(SkPoint::Make(SkScalarMul(point.x(), fPaintingData->fBaseFrequency.fX),
383                                       SkScalarMul(point.y(), fPaintingData->fBaseFrequency.fY)));
384     SkScalar ratio = SK_Scalar1;
385     for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) {
386         SkScalar noise = noise2D(channel, stitchData, noiseVector);
387         SkScalar numer = (perlinNoiseShader.fType == kFractalNoise_Type) ?
388                             noise : SkScalarAbs(noise);
389         turbulenceFunctionResult += numer / ratio;
390         noiseVector.fX *= 2;
391         noiseVector.fY *= 2;
392         ratio *= 2;
393         if (perlinNoiseShader.fStitchTiles) {
394             // Update stitch values
395             stitchData.fWidth  *= 2;
396             stitchData.fWrapX   = stitchData.fWidth + kPerlinNoise;
397             stitchData.fHeight *= 2;
398             stitchData.fWrapY   = stitchData.fHeight + kPerlinNoise;
399         }
400     }
401 
402     // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
403     // by fractalNoise and (turbulenceFunctionResult) by turbulence.
404     if (perlinNoiseShader.fType == kFractalNoise_Type) {
405         turbulenceFunctionResult =
406             SkScalarMul(turbulenceFunctionResult, SK_ScalarHalf) + SK_ScalarHalf;
407     }
408 
409     if (channel == 3) { // Scale alpha by paint value
410         turbulenceFunctionResult *= SkIntToScalar(getPaintAlpha()) / 255;
411     }
412 
413     // Clamp result
414     return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1);
415 }
416 
shade(const SkPoint & point,StitchData & stitchData) const417 SkPMColor SkPerlinNoiseShader::PerlinNoiseShaderContext::shade(
418         const SkPoint& point, StitchData& stitchData) const {
419     SkPoint newPoint;
420     fMatrix.mapPoints(&newPoint, &point, 1);
421     newPoint.fX = SkScalarRoundToScalar(newPoint.fX);
422     newPoint.fY = SkScalarRoundToScalar(newPoint.fY);
423 
424     U8CPU rgba[4];
425     for (int channel = 3; channel >= 0; --channel) {
426         rgba[channel] = SkScalarFloorToInt(255 *
427             calculateTurbulenceValueForPoint(channel, stitchData, newPoint));
428     }
429     return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]);
430 }
431 
onCreateContext(const ContextRec & rec,void * storage) const432 SkShader::Context* SkPerlinNoiseShader::onCreateContext(const ContextRec& rec,
433                                                         void* storage) const {
434     return new (storage) PerlinNoiseShaderContext(*this, rec);
435 }
436 
contextSize(const ContextRec &) const437 size_t SkPerlinNoiseShader::contextSize(const ContextRec&) const {
438     return sizeof(PerlinNoiseShaderContext);
439 }
440 
PerlinNoiseShaderContext(const SkPerlinNoiseShader & shader,const ContextRec & rec)441 SkPerlinNoiseShader::PerlinNoiseShaderContext::PerlinNoiseShaderContext(
442         const SkPerlinNoiseShader& shader, const ContextRec& rec)
443     : INHERITED(shader, rec)
444 {
445     SkMatrix newMatrix = *rec.fMatrix;
446     newMatrix.preConcat(shader.getLocalMatrix());
447     if (rec.fLocalMatrix) {
448         newMatrix.preConcat(*rec.fLocalMatrix);
449     }
450     // This (1,1) translation is due to WebKit's 1 based coordinates for the noise
451     // (as opposed to 0 based, usually). The same adjustment is in the setData() function.
452     fMatrix.setTranslate(-newMatrix.getTranslateX() + SK_Scalar1, -newMatrix.getTranslateY() + SK_Scalar1);
453     fPaintingData = new PaintingData(shader.fTileSize, shader.fSeed, shader.fBaseFrequencyX,
454                                      shader.fBaseFrequencyY, newMatrix);
455 }
456 
~PerlinNoiseShaderContext()457 SkPerlinNoiseShader::PerlinNoiseShaderContext::~PerlinNoiseShaderContext() { delete fPaintingData; }
458 
shadeSpan(int x,int y,SkPMColor result[],int count)459 void SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan(
460         int x, int y, SkPMColor result[], int count) {
461     SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
462     StitchData stitchData;
463     for (int i = 0; i < count; ++i) {
464         result[i] = shade(point, stitchData);
465         point.fX += SK_Scalar1;
466     }
467 }
468 
469 /////////////////////////////////////////////////////////////////////
470 
471 #if SK_SUPPORT_GPU
472 
473 class GrGLPerlinNoise : public GrGLSLFragmentProcessor {
474 public:
475     void emitCode(EmitArgs&) override;
476 
477     static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*);
478 
479 protected:
480     void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
481 
482 private:
483     GrGLSLProgramDataManager::UniformHandle fStitchDataUni;
484     GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
485 
486     typedef GrGLSLFragmentProcessor INHERITED;
487 };
488 
489 /////////////////////////////////////////////////////////////////////
490 
491 class GrPerlinNoiseEffect : public GrFragmentProcessor {
492 public:
Create(SkPerlinNoiseShader::Type type,int numOctaves,bool stitchTiles,SkPerlinNoiseShader::PaintingData * paintingData,GrTexture * permutationsTexture,GrTexture * noiseTexture,const SkMatrix & matrix)493     static GrFragmentProcessor* Create(SkPerlinNoiseShader::Type type,
494                                        int numOctaves, bool stitchTiles,
495                                        SkPerlinNoiseShader::PaintingData* paintingData,
496                                        GrTexture* permutationsTexture, GrTexture* noiseTexture,
497                                        const SkMatrix& matrix) {
498         return new GrPerlinNoiseEffect(type, numOctaves, stitchTiles, paintingData,
499                                        permutationsTexture, noiseTexture, matrix);
500     }
501 
~GrPerlinNoiseEffect()502     virtual ~GrPerlinNoiseEffect() { delete fPaintingData; }
503 
name() const504     const char* name() const override { return "PerlinNoise"; }
505 
stitchData() const506     const SkPerlinNoiseShader::StitchData& stitchData() const { return fPaintingData->fStitchDataInit; }
507 
type() const508     SkPerlinNoiseShader::Type type() const { return fType; }
stitchTiles() const509     bool stitchTiles() const { return fStitchTiles; }
baseFrequency() const510     const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
numOctaves() const511     int numOctaves() const { return fNumOctaves; }
matrix() const512     const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
513 
514 private:
onCreateGLSLInstance() const515     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
516         return new GrGLPerlinNoise;
517     }
518 
onGetGLSLProcessorKey(const GrGLSLCaps & caps,GrProcessorKeyBuilder * b) const519     virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps,
520                                        GrProcessorKeyBuilder* b) const override {
521         GrGLPerlinNoise::GenKey(*this, caps, b);
522     }
523 
onIsEqual(const GrFragmentProcessor & sBase) const524     bool onIsEqual(const GrFragmentProcessor& sBase) const override {
525         const GrPerlinNoiseEffect& s = sBase.cast<GrPerlinNoiseEffect>();
526         return fType == s.fType &&
527                fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency &&
528                fNumOctaves == s.fNumOctaves &&
529                fStitchTiles == s.fStitchTiles &&
530                fPaintingData->fStitchDataInit == s.fPaintingData->fStitchDataInit;
531     }
532 
onComputeInvariantOutput(GrInvariantOutput * inout) const533     void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
534         inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput);
535     }
536 
GrPerlinNoiseEffect(SkPerlinNoiseShader::Type type,int numOctaves,bool stitchTiles,SkPerlinNoiseShader::PaintingData * paintingData,GrTexture * permutationsTexture,GrTexture * noiseTexture,const SkMatrix & matrix)537     GrPerlinNoiseEffect(SkPerlinNoiseShader::Type type,
538                         int numOctaves, bool stitchTiles,
539                         SkPerlinNoiseShader::PaintingData* paintingData,
540                         GrTexture* permutationsTexture, GrTexture* noiseTexture,
541                         const SkMatrix& matrix)
542       : fType(type)
543       , fNumOctaves(numOctaves)
544       , fStitchTiles(stitchTiles)
545       , fPermutationsAccess(permutationsTexture)
546       , fNoiseAccess(noiseTexture)
547       , fPaintingData(paintingData) {
548         this->initClassID<GrPerlinNoiseEffect>();
549         this->addTextureAccess(&fPermutationsAccess);
550         this->addTextureAccess(&fNoiseAccess);
551         fCoordTransform.reset(kLocal_GrCoordSet, matrix);
552         this->addCoordTransform(&fCoordTransform);
553     }
554 
555     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
556 
557     SkPerlinNoiseShader::Type       fType;
558     GrCoordTransform                fCoordTransform;
559     int                             fNumOctaves;
560     bool                            fStitchTiles;
561     GrTextureAccess                 fPermutationsAccess;
562     GrTextureAccess                 fNoiseAccess;
563     SkPerlinNoiseShader::PaintingData *fPaintingData;
564 
565 private:
566     typedef GrFragmentProcessor INHERITED;
567 };
568 
569 /////////////////////////////////////////////////////////////////////
570 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrPerlinNoiseEffect);
571 
TestCreate(GrProcessorTestData * d)572 const GrFragmentProcessor* GrPerlinNoiseEffect::TestCreate(GrProcessorTestData* d) {
573     int      numOctaves = d->fRandom->nextRangeU(2, 10);
574     bool     stitchTiles = d->fRandom->nextBool();
575     SkScalar seed = SkIntToScalar(d->fRandom->nextU());
576     SkISize  tileSize = SkISize::Make(d->fRandom->nextRangeU(4, 4096),
577                                       d->fRandom->nextRangeU(4, 4096));
578     SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
579                                                           0.99f);
580     SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
581                                                           0.99f);
582 
583     SkAutoTUnref<SkShader> shader(d->fRandom->nextBool() ?
584         SkPerlinNoiseShader::CreateFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves, seed,
585                                                 stitchTiles ? &tileSize : nullptr) :
586         SkPerlinNoiseShader::CreateTurbulence(baseFrequencyX, baseFrequencyY, numOctaves, seed,
587                                              stitchTiles ? &tileSize : nullptr));
588 
589     return shader->asFragmentProcessor(d->fContext,
590                                        GrTest::TestMatrix(d->fRandom), nullptr,
591                                        kNone_SkFilterQuality);
592 }
593 
emitCode(EmitArgs & args)594 void GrGLPerlinNoise::emitCode(EmitArgs& args) {
595     const GrPerlinNoiseEffect& pne = args.fFp.cast<GrPerlinNoiseEffect>();
596 
597     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
598     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
599     SkString vCoords = fragBuilder->ensureFSCoords2D(args.fCoords, 0);
600 
601     fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
602                                                    kVec2f_GrSLType, kDefault_GrSLPrecision,
603                                                    "baseFrequency");
604     const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
605 
606     const char* stitchDataUni = nullptr;
607     if (pne.stitchTiles()) {
608         fStitchDataUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
609                                                     kVec2f_GrSLType, kDefault_GrSLPrecision,
610                                                     "stitchData");
611         stitchDataUni = uniformHandler->getUniformCStr(fStitchDataUni);
612     }
613 
614     // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8
615     const char* chanCoordR  = "0.125";
616     const char* chanCoordG  = "0.375";
617     const char* chanCoordB  = "0.625";
618     const char* chanCoordA  = "0.875";
619     const char* chanCoord   = "chanCoord";
620     const char* stitchData  = "stitchData";
621     const char* ratio       = "ratio";
622     const char* noiseVec    = "noiseVec";
623     const char* noiseSmooth = "noiseSmooth";
624     const char* floorVal    = "floorVal";
625     const char* fractVal    = "fractVal";
626     const char* uv          = "uv";
627     const char* ab          = "ab";
628     const char* latticeIdx  = "latticeIdx";
629     const char* bcoords     = "bcoords";
630     const char* lattice     = "lattice";
631     const char* inc8bit     = "0.00390625";  // 1.0 / 256.0
632     // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a
633     // [-1,1] vector and perform a dot product between that vector and the provided vector.
634     const char* dotLattice  = "dot(((%s.ga + %s.rb * vec2(%s)) * vec2(2.0) - vec2(1.0)), %s);";
635 
636     // Add noise function
637     static const GrGLSLShaderVar gPerlinNoiseArgs[] =  {
638         GrGLSLShaderVar(chanCoord, kFloat_GrSLType),
639         GrGLSLShaderVar(noiseVec, kVec2f_GrSLType)
640     };
641 
642     static const GrGLSLShaderVar gPerlinNoiseStitchArgs[] =  {
643         GrGLSLShaderVar(chanCoord, kFloat_GrSLType),
644         GrGLSLShaderVar(noiseVec, kVec2f_GrSLType),
645         GrGLSLShaderVar(stitchData, kVec2f_GrSLType)
646     };
647 
648     SkString noiseCode;
649 
650     noiseCode.appendf("\tvec4 %s;\n", floorVal);
651     noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec);
652     noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal);
653     noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec);
654 
655     // smooth curve : t * t * (3 - 2 * t)
656     noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);",
657         noiseSmooth, fractVal, fractVal, fractVal);
658 
659     // Adjust frequencies if we're stitching tiles
660     if (pne.stitchTiles()) {
661         noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }",
662                           floorVal, stitchData, floorVal, stitchData);
663         noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }",
664                           floorVal, stitchData, floorVal, stitchData);
665         noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }",
666                           floorVal, stitchData, floorVal, stitchData);
667         noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }",
668                           floorVal, stitchData, floorVal, stitchData);
669     }
670 
671     // Get texture coordinates and normalize
672     noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / vec4(256.0));\n",
673                       floorVal, floorVal);
674 
675     // Get permutation for x
676     {
677         SkString xCoords("");
678         xCoords.appendf("vec2(%s.x, 0.5)", floorVal);
679 
680         noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
681         fragBuilder->appendTextureLookup(&noiseCode, args.fSamplers[0], xCoords.c_str(),
682                                          kVec2f_GrSLType);
683         noiseCode.append(".r;");
684     }
685 
686     // Get permutation for x + 1
687     {
688         SkString xCoords("");
689         xCoords.appendf("vec2(%s.z, 0.5)", floorVal);
690 
691         noiseCode.appendf("\n\t%s.y = ", latticeIdx);
692         fragBuilder->appendTextureLookup(&noiseCode, args.fSamplers[0], xCoords.c_str(),
693                                          kVec2f_GrSLType);
694         noiseCode.append(".r;");
695     }
696 
697 #if defined(SK_BUILD_FOR_ANDROID)
698     // Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3).
699     // The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit
700     // value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725
701     // (or 0.484368 here). The following rounding operation prevents these precision issues from
702     // affecting the result of the noise by making sure that we only have multiples of 1/255.
703     // (Note that 1/255 is about 0.003921569, which is the value used here).
704     noiseCode.appendf("\n\t%s = floor(%s * vec2(255.0) + vec2(0.5)) * vec2(0.003921569);",
705                       latticeIdx, latticeIdx);
706 #endif
707 
708     // Get (x,y) coordinates with the permutated x
709     noiseCode.appendf("\n\tvec4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal);
710 
711     noiseCode.appendf("\n\n\tvec2 %s;", uv);
712     // Compute u, at offset (0,0)
713     {
714         SkString latticeCoords("");
715         latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord);
716         noiseCode.appendf("\n\tvec4 %s = ", lattice);
717         fragBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
718                                          kVec2f_GrSLType);
719         noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
720         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
721     }
722 
723     noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal);
724     // Compute v, at offset (-1,0)
725     {
726         SkString latticeCoords("");
727         latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord);
728         noiseCode.append("\n\tlattice = ");
729         fragBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
730                                          kVec2f_GrSLType);
731         noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
732         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
733     }
734 
735     // Compute 'a' as a linear interpolation of 'u' and 'v'
736     noiseCode.appendf("\n\tvec2 %s;", ab);
737     noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
738 
739     noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal);
740     // Compute v, at offset (-1,-1)
741     {
742         SkString latticeCoords("");
743         latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord);
744         noiseCode.append("\n\tlattice = ");
745         fragBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
746                                          kVec2f_GrSLType);
747         noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
748         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
749     }
750 
751     noiseCode.appendf("\n\t%s.x += 1.0;", fractVal);
752     // Compute u, at offset (0,-1)
753     {
754         SkString latticeCoords("");
755         latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord);
756         noiseCode.append("\n\tlattice = ");
757         fragBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
758                                          kVec2f_GrSLType);
759         noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
760         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
761     }
762 
763     // Compute 'b' as a linear interpolation of 'u' and 'v'
764     noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
765     // Compute the noise as a linear interpolation of 'a' and 'b'
766     noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth);
767 
768     SkString noiseFuncName;
769     if (pne.stitchTiles()) {
770         fragBuilder->emitFunction(kFloat_GrSLType,
771                                   "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs),
772                                   gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName);
773     } else {
774         fragBuilder->emitFunction(kFloat_GrSLType,
775                                   "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs),
776                                   gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName);
777     }
778 
779     // There are rounding errors if the floor operation is not performed here
780     fragBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;",
781                              noiseVec, vCoords.c_str(), baseFrequencyUni);
782 
783     // Clear the color accumulator
784     fragBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", args.fOutputColor);
785 
786     if (pne.stitchTiles()) {
787         // Set up TurbulenceInitial stitch values.
788         fragBuilder->codeAppendf("vec2 %s = %s;", stitchData, stitchDataUni);
789     }
790 
791     fragBuilder->codeAppendf("float %s = 1.0;", ratio);
792 
793     // Loop over all octaves
794     fragBuilder->codeAppendf("for (int octave = 0; octave < %d; ++octave) {", pne.numOctaves());
795 
796     fragBuilder->codeAppendf("%s += ", args.fOutputColor);
797     if (pne.type() != SkPerlinNoiseShader::kFractalNoise_Type) {
798         fragBuilder->codeAppend("abs(");
799     }
800     if (pne.stitchTiles()) {
801         fragBuilder->codeAppendf(
802             "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s),"
803                  "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))",
804             noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData,
805             noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData,
806             noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData,
807             noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData);
808     } else {
809         fragBuilder->codeAppendf(
810             "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s),"
811                  "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))",
812             noiseFuncName.c_str(), chanCoordR, noiseVec,
813             noiseFuncName.c_str(), chanCoordG, noiseVec,
814             noiseFuncName.c_str(), chanCoordB, noiseVec,
815             noiseFuncName.c_str(), chanCoordA, noiseVec);
816     }
817     if (pne.type() != SkPerlinNoiseShader::kFractalNoise_Type) {
818         fragBuilder->codeAppendf(")"); // end of "abs("
819     }
820     fragBuilder->codeAppendf(" * %s;", ratio);
821 
822     fragBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec);
823     fragBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio);
824 
825     if (pne.stitchTiles()) {
826         fragBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData);
827     }
828     fragBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves
829 
830     if (pne.type() == SkPerlinNoiseShader::kFractalNoise_Type) {
831         // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
832         // by fractalNoise and (turbulenceFunctionResult) by turbulence.
833         fragBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);",
834                                  args.fOutputColor,args.fOutputColor);
835     }
836 
837     // Clamp values
838     fragBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
839 
840     // Pre-multiply the result
841     fragBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
842                              args.fOutputColor, args.fOutputColor,
843                              args.fOutputColor, args.fOutputColor);
844 }
845 
GenKey(const GrProcessor & processor,const GrGLSLCaps &,GrProcessorKeyBuilder * b)846 void GrGLPerlinNoise::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
847                              GrProcessorKeyBuilder* b) {
848     const GrPerlinNoiseEffect& turbulence = processor.cast<GrPerlinNoiseEffect>();
849 
850     uint32_t key = turbulence.numOctaves();
851 
852     key = key << 3; // Make room for next 3 bits
853 
854     switch (turbulence.type()) {
855         case SkPerlinNoiseShader::kFractalNoise_Type:
856             key |= 0x1;
857             break;
858         case SkPerlinNoiseShader::kTurbulence_Type:
859             key |= 0x2;
860             break;
861         default:
862             // leave key at 0
863             break;
864     }
865 
866     if (turbulence.stitchTiles()) {
867         key |= 0x4; // Flip the 3rd bit if tile stitching is on
868     }
869 
870     b->add32(key);
871 }
872 
onSetData(const GrGLSLProgramDataManager & pdman,const GrProcessor & processor)873 void GrGLPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman,
874                                 const GrProcessor& processor) {
875     INHERITED::onSetData(pdman, processor);
876 
877     const GrPerlinNoiseEffect& turbulence = processor.cast<GrPerlinNoiseEffect>();
878 
879     const SkVector& baseFrequency = turbulence.baseFrequency();
880     pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
881 
882     if (turbulence.stitchTiles()) {
883         const SkPerlinNoiseShader::StitchData& stitchData = turbulence.stitchData();
884         pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth),
885                                    SkIntToScalar(stitchData.fHeight));
886     }
887 }
888 
889 /////////////////////////////////////////////////////////////////////
asFragmentProcessor(GrContext * context,const SkMatrix & viewM,const SkMatrix * externalLocalMatrix,SkFilterQuality) const890 const GrFragmentProcessor* SkPerlinNoiseShader::asFragmentProcessor(
891                                                     GrContext* context,
892                                                     const SkMatrix& viewM,
893                                                     const SkMatrix* externalLocalMatrix,
894                                                     SkFilterQuality) const {
895     SkASSERT(context);
896 
897     SkMatrix localMatrix = this->getLocalMatrix();
898     if (externalLocalMatrix) {
899         localMatrix.preConcat(*externalLocalMatrix);
900     }
901 
902     SkMatrix matrix = viewM;
903     matrix.preConcat(localMatrix);
904 
905     if (0 == fNumOctaves) {
906         if (kFractalNoise_Type == fType) {
907             // Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2)
908             SkAutoTUnref<const GrFragmentProcessor> inner(
909                 GrConstColorProcessor::Create(0x80404040,
910                                               GrConstColorProcessor::kModulateRGBA_InputMode));
911             return GrFragmentProcessor::MulOutputByInputAlpha(inner);
912         }
913         // Emit zero.
914         return GrConstColorProcessor::Create(0x0, GrConstColorProcessor::kIgnore_InputMode);
915     }
916 
917     // Either we don't stitch tiles, either we have a valid tile size
918     SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
919 
920     SkPerlinNoiseShader::PaintingData* paintingData =
921             new PaintingData(fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY, matrix);
922     SkAutoTUnref<GrTexture> permutationsTexture(
923         GrRefCachedBitmapTexture(context, paintingData->getPermutationsBitmap(),
924                                  GrTextureParams::ClampNoFilter()));
925     SkAutoTUnref<GrTexture> noiseTexture(
926         GrRefCachedBitmapTexture(context, paintingData->getNoiseBitmap(),
927                                  GrTextureParams::ClampNoFilter()));
928 
929     SkMatrix m = viewM;
930     m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1);
931     m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1);
932     if ((permutationsTexture) && (noiseTexture)) {
933         SkAutoTUnref<GrFragmentProcessor> inner(
934             GrPerlinNoiseEffect::Create(fType,
935                                         fNumOctaves,
936                                         fStitchTiles,
937                                         paintingData,
938                                         permutationsTexture, noiseTexture,
939                                         m));
940         return GrFragmentProcessor::MulOutputByInputAlpha(inner);
941     }
942     delete paintingData;
943     return nullptr;
944 }
945 
946 #endif
947 
948 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const949 void SkPerlinNoiseShader::toString(SkString* str) const {
950     str->append("SkPerlinNoiseShader: (");
951 
952     str->append("type: ");
953     switch (fType) {
954         case kFractalNoise_Type:
955             str->append("\"fractal noise\"");
956             break;
957         case kTurbulence_Type:
958             str->append("\"turbulence\"");
959             break;
960         default:
961             str->append("\"unknown\"");
962             break;
963     }
964     str->append(" base frequency: (");
965     str->appendScalar(fBaseFrequencyX);
966     str->append(", ");
967     str->appendScalar(fBaseFrequencyY);
968     str->append(") number of octaves: ");
969     str->appendS32(fNumOctaves);
970     str->append(" seed: ");
971     str->appendScalar(fSeed);
972     str->append(" stitch tiles: ");
973     str->append(fStitchTiles ? "true " : "false ");
974 
975     this->INHERITED::toString(str);
976 
977     str->append(")");
978 }
979 #endif
980