• 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 "SkPerlinNoiseShader2.h"
9 
10 #include "SkArenaAlloc.h"
11 #include "SkDither.h"
12 #include "SkColorFilter.h"
13 #include "SkReadBuffer.h"
14 #include "SkWriteBuffer.h"
15 #include "SkShader.h"
16 #include "SkUnPreMultiply.h"
17 #include "SkString.h"
18 
19 #if SK_SUPPORT_GPU
20 #include "GrContext.h"
21 #include "GrCoordTransform.h"
22 #include "SkGr.h"
23 #include "effects/GrConstColorProcessor.h"
24 #include "glsl/GrGLSLFragmentProcessor.h"
25 #include "glsl/GrGLSLFragmentShaderBuilder.h"
26 #include "glsl/GrGLSLProgramDataManager.h"
27 #include "glsl/GrGLSLUniformHandler.h"
28 #endif
29 
30 static const int kBlockSize = 256;
31 static const int kBlockMask = kBlockSize - 1;
32 static const int kPerlinNoise = 4096;
33 static const int kRandMaximum = SK_MaxS32; // 2**31 - 1
34 
35 static uint8_t improved_noise_permutations[] = {
36     151, 160, 137,  91,  90,  15, 131,  13, 201,  95,  96,  53, 194, 233,   7, 225, 140,  36, 103,
37      30,  69, 142,   8,  99,  37, 240,  21,  10,  23, 190,   6, 148, 247, 120, 234,  75,   0,  26,
38     197,  62,  94, 252, 219, 203, 117,  35,  11,  32,  57, 177,  33,  88, 237, 149,  56,  87, 174,
39      20, 125, 136, 171, 168,  68, 175,  74, 165,  71, 134, 139,  48,  27, 166,  77, 146, 158, 231,
40      83, 111, 229, 122,  60, 211, 133, 230, 220, 105,  92,  41,  55,  46, 245,  40, 244, 102, 143,
41      54,  65,  25,  63, 161,   1, 216,  80,  73, 209,  76, 132, 187, 208,  89,  18, 169, 200, 196,
42     135, 130, 116, 188, 159,  86, 164, 100, 109, 198, 173, 186,   3,  64,  52, 217, 226, 250, 124,
43     123,   5, 202,  38, 147, 118, 126, 255,  82,  85, 212, 207, 206,  59, 227,  47,  16,  58,  17,
44     182, 189,  28,  42, 223, 183, 170, 213, 119, 248, 152,   2,  44, 154, 163,  70, 221, 153, 101,
45     155, 167,  43, 172,   9, 129,  22,  39, 253,  19,  98, 108, 110,  79, 113, 224, 232, 178, 185,
46     112, 104, 218, 246,  97, 228, 251,  34, 242, 193, 238, 210, 144,  12, 191, 179, 162, 241,  81,
47      51, 145, 235, 249,  14, 239, 107,  49, 192, 214,  31, 181, 199, 106, 157, 184,  84, 204, 176,
48     115, 121,  50,  45, 127,   4, 150, 254, 138, 236, 205,  93, 222, 114,  67,  29,  24,  72, 243,
49     141, 128, 195,  78,  66, 215,  61, 156, 180,
50     151, 160, 137,  91,  90,  15, 131,  13, 201,  95,  96,  53, 194, 233,   7, 225, 140,  36, 103,
51      30,  69, 142,   8,  99,  37, 240,  21,  10,  23, 190,   6, 148, 247, 120, 234,  75,   0,  26,
52     197,  62,  94, 252, 219, 203, 117,  35,  11,  32,  57, 177,  33,  88, 237, 149,  56,  87, 174,
53      20, 125, 136, 171, 168,  68, 175,  74, 165,  71, 134, 139,  48,  27, 166,  77, 146, 158, 231,
54      83, 111, 229, 122,  60, 211, 133, 230, 220, 105,  92,  41,  55,  46, 245,  40, 244, 102, 143,
55      54,  65,  25,  63, 161,   1, 216,  80,  73, 209,  76, 132, 187, 208,  89,  18, 169, 200, 196,
56     135, 130, 116, 188, 159,  86, 164, 100, 109, 198, 173, 186,   3,  64,  52, 217, 226, 250, 124,
57     123,   5, 202,  38, 147, 118, 126, 255,  82,  85, 212, 207, 206,  59, 227,  47,  16,  58,  17,
58     182, 189,  28,  42, 223, 183, 170, 213, 119, 248, 152,   2,  44, 154, 163,  70, 221, 153, 101,
59     155, 167,  43, 172,   9, 129,  22,  39, 253,  19,  98, 108, 110,  79, 113, 224, 232, 178, 185,
60     112, 104, 218, 246,  97, 228, 251,  34, 242, 193, 238, 210, 144,  12, 191, 179, 162, 241,  81,
61      51, 145, 235, 249,  14, 239, 107,  49, 192, 214,  31, 181, 199, 106, 157, 184,  84, 204, 176,
62     115, 121,  50,  45, 127,   4, 150, 254, 138, 236, 205,  93, 222, 114,  67,  29,  24,  72, 243,
63     141, 128, 195,  78,  66, 215,  61, 156, 180
64 };
65 
66 namespace {
67 
68 // noiseValue is the color component's value (or color)
69 // limitValue is the maximum perlin noise array index value allowed
70 // newValue is the current noise dimension (either width or height)
checkNoise(int noiseValue,int limitValue,int newValue)71 inline int checkNoise(int noiseValue, int limitValue, int newValue) {
72     // If the noise value would bring us out of bounds of the current noise array while we are
73     // stiching noise tiles together, wrap the noise around the current dimension of the noise to
74     // stay within the array bounds in a continuous fashion (so that tiling lines are not visible)
75     if (noiseValue >= limitValue) {
76         noiseValue -= newValue;
77     }
78     return noiseValue;
79 }
80 
smoothCurve(SkScalar t)81 inline SkScalar smoothCurve(SkScalar t) {
82     return t * t * (3 - 2 * t);
83 }
84 
85 } // end namespace
86 
87 struct SkPerlinNoiseShader2::StitchData {
StitchDataSkPerlinNoiseShader2::StitchData88     StitchData()
89       : fWidth(0)
90       , fWrapX(0)
91       , fHeight(0)
92       , fWrapY(0)
93     {}
94 
operator ==SkPerlinNoiseShader2::StitchData95     bool operator==(const StitchData& other) const {
96         return fWidth == other.fWidth &&
97                fWrapX == other.fWrapX &&
98                fHeight == other.fHeight &&
99                fWrapY == other.fWrapY;
100     }
101 
102     int fWidth; // How much to subtract to wrap for stitching.
103     int fWrapX; // Minimum value to wrap.
104     int fHeight;
105     int fWrapY;
106 };
107 
108 struct SkPerlinNoiseShader2::PaintingData {
PaintingDataSkPerlinNoiseShader2::PaintingData109     PaintingData(const SkISize& tileSize, SkScalar seed,
110                  SkScalar baseFrequencyX, SkScalar baseFrequencyY,
111                  const SkMatrix& matrix)
112     {
113         SkVector vec[2] = {
114             { SkScalarInvert(baseFrequencyX),   SkScalarInvert(baseFrequencyY)  },
115             { SkIntToScalar(tileSize.fWidth),   SkIntToScalar(tileSize.fHeight) },
116         };
117         matrix.mapVectors(vec, 2);
118 
119         fBaseFrequency.set(SkScalarInvert(vec[0].fX), SkScalarInvert(vec[0].fY));
120         fTileSize.set(SkScalarRoundToInt(vec[1].fX), SkScalarRoundToInt(vec[1].fY));
121         this->init(seed);
122         if (!fTileSize.isEmpty()) {
123             this->stitch();
124         }
125 
126 #if SK_SUPPORT_GPU
127         fPermutationsBitmap.setInfo(SkImageInfo::MakeA8(kBlockSize, 1));
128         fPermutationsBitmap.setPixels(fLatticeSelector);
129 
130         fNoiseBitmap.setInfo(SkImageInfo::MakeN32Premul(kBlockSize, 4));
131         fNoiseBitmap.setPixels(fNoise[0][0]);
132 
133         fImprovedPermutationsBitmap.setInfo(SkImageInfo::MakeA8(256, 1));
134         fImprovedPermutationsBitmap.setPixels(improved_noise_permutations);
135 
136         fGradientBitmap.setInfo(SkImageInfo::MakeN32Premul(16, 1));
137         static uint8_t gradients[] = { 2, 2, 1, 0,
138                                        0, 2, 1, 0,
139                                        2, 0, 1, 0,
140                                        0, 0, 1, 0,
141                                        2, 1, 2, 0,
142                                        0, 1, 2, 0,
143                                        2, 1, 0, 0,
144                                        0, 1, 0, 0,
145                                        1, 2, 2, 0,
146                                        1, 0, 2, 0,
147                                        1, 2, 0, 0,
148                                        1, 0, 0, 0,
149                                        2, 2, 1, 0,
150                                        1, 0, 2, 0,
151                                        0, 2, 1, 0,
152                                        1, 0, 0, 0 };
153         fGradientBitmap.setPixels(gradients);
154 #endif
155     }
156 
157     int         fSeed;
158     uint8_t     fLatticeSelector[kBlockSize];
159     uint16_t    fNoise[4][kBlockSize][2];
160     SkPoint     fGradient[4][kBlockSize];
161     SkISize     fTileSize;
162     SkVector    fBaseFrequency;
163     StitchData  fStitchDataInit;
164 
165 private:
166 
167 #if SK_SUPPORT_GPU
168     SkBitmap   fPermutationsBitmap;
169     SkBitmap   fNoiseBitmap;
170     SkBitmap   fImprovedPermutationsBitmap;
171     SkBitmap   fGradientBitmap;
172 #endif
173 
randomSkPerlinNoiseShader2::PaintingData174     inline int random()  {
175         static const int gRandAmplitude = 16807; // 7**5; primitive root of m
176         static const int gRandQ = 127773; // m / a
177         static const int gRandR = 2836; // m % a
178 
179         int result = gRandAmplitude * (fSeed % gRandQ) - gRandR * (fSeed / gRandQ);
180         if (result <= 0)
181             result += kRandMaximum;
182         fSeed = result;
183         return result;
184     }
185 
186     // Only called once. Could be part of the constructor.
initSkPerlinNoiseShader2::PaintingData187     void init(SkScalar seed)
188     {
189         static const SkScalar gInvBlockSizef = SkScalarInvert(SkIntToScalar(kBlockSize));
190 
191         // According to the SVG spec, we must truncate (not round) the seed value.
192         fSeed = SkScalarTruncToInt(seed);
193         // The seed value clamp to the range [1, kRandMaximum - 1].
194         if (fSeed <= 0) {
195             fSeed = -(fSeed % (kRandMaximum - 1)) + 1;
196         }
197         if (fSeed > kRandMaximum - 1) {
198             fSeed = kRandMaximum - 1;
199         }
200         for (int channel = 0; channel < 4; ++channel) {
201             for (int i = 0; i < kBlockSize; ++i) {
202                 fLatticeSelector[i] = i;
203                 fNoise[channel][i][0] = (random() % (2 * kBlockSize));
204                 fNoise[channel][i][1] = (random() % (2 * kBlockSize));
205             }
206         }
207         for (int i = kBlockSize - 1; i > 0; --i) {
208             int k = fLatticeSelector[i];
209             int j = random() % kBlockSize;
210             SkASSERT(j >= 0);
211             SkASSERT(j < kBlockSize);
212             fLatticeSelector[i] = fLatticeSelector[j];
213             fLatticeSelector[j] = k;
214         }
215 
216         // Perform the permutations now
217         {
218             // Copy noise data
219             uint16_t noise[4][kBlockSize][2];
220             for (int i = 0; i < kBlockSize; ++i) {
221                 for (int channel = 0; channel < 4; ++channel) {
222                     for (int j = 0; j < 2; ++j) {
223                         noise[channel][i][j] = fNoise[channel][i][j];
224                     }
225                 }
226             }
227             // Do permutations on noise data
228             for (int i = 0; i < kBlockSize; ++i) {
229                 for (int channel = 0; channel < 4; ++channel) {
230                     for (int j = 0; j < 2; ++j) {
231                         fNoise[channel][i][j] = noise[channel][fLatticeSelector[i]][j];
232                     }
233                 }
234             }
235         }
236 
237         // Half of the largest possible value for 16 bit unsigned int
238         static const SkScalar gHalfMax16bits = 32767.5f;
239 
240         // Compute gradients from permutated noise data
241         for (int channel = 0; channel < 4; ++channel) {
242             for (int i = 0; i < kBlockSize; ++i) {
243                 fGradient[channel][i] = SkPoint::Make(
244                     (fNoise[channel][i][0] - kBlockSize) * gInvBlockSizef,
245                     (fNoise[channel][i][1] - kBlockSize) * gInvBlockSizef);
246                 fGradient[channel][i].normalize();
247                 // Put the normalized gradient back into the noise data
248                 fNoise[channel][i][0] = SkScalarRoundToInt(
249                                                (fGradient[channel][i].fX + 1) * gHalfMax16bits);
250                 fNoise[channel][i][1] = SkScalarRoundToInt(
251                                                (fGradient[channel][i].fY + 1) * gHalfMax16bits);
252             }
253         }
254     }
255 
256     // Only called once. Could be part of the constructor.
stitchSkPerlinNoiseShader2::PaintingData257     void stitch() {
258         SkScalar tileWidth  = SkIntToScalar(fTileSize.width());
259         SkScalar tileHeight = SkIntToScalar(fTileSize.height());
260         SkASSERT(tileWidth > 0 && tileHeight > 0);
261         // When stitching tiled turbulence, the frequencies must be adjusted
262         // so that the tile borders will be continuous.
263         if (fBaseFrequency.fX) {
264             SkScalar lowFrequencx =
265                 SkScalarFloorToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
266             SkScalar highFrequencx =
267                 SkScalarCeilToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
268             // BaseFrequency should be non-negative according to the standard.
269             if (fBaseFrequency.fX / lowFrequencx < highFrequencx / fBaseFrequency.fX) {
270                 fBaseFrequency.fX = lowFrequencx;
271             } else {
272                 fBaseFrequency.fX = highFrequencx;
273             }
274         }
275         if (fBaseFrequency.fY) {
276             SkScalar lowFrequency =
277                 SkScalarFloorToScalar(tileHeight * fBaseFrequency.fY) / tileHeight;
278             SkScalar highFrequency =
279                 SkScalarCeilToScalar(tileHeight * fBaseFrequency.fY) / tileHeight;
280             if (fBaseFrequency.fY / lowFrequency < highFrequency / fBaseFrequency.fY) {
281                 fBaseFrequency.fY = lowFrequency;
282             } else {
283                 fBaseFrequency.fY = highFrequency;
284             }
285         }
286         // Set up TurbulenceInitial stitch values.
287         fStitchDataInit.fWidth  =
288             SkScalarRoundToInt(tileWidth * fBaseFrequency.fX);
289         fStitchDataInit.fWrapX  = kPerlinNoise + fStitchDataInit.fWidth;
290         fStitchDataInit.fHeight =
291             SkScalarRoundToInt(tileHeight * fBaseFrequency.fY);
292         fStitchDataInit.fWrapY  = kPerlinNoise + fStitchDataInit.fHeight;
293     }
294 
295 public:
296 
297 #if SK_SUPPORT_GPU
getPermutationsBitmapSkPerlinNoiseShader2::PaintingData298     const SkBitmap& getPermutationsBitmap() const { return fPermutationsBitmap; }
299 
getNoiseBitmapSkPerlinNoiseShader2::PaintingData300     const SkBitmap& getNoiseBitmap() const { return fNoiseBitmap; }
301 
getImprovedPermutationsBitmapSkPerlinNoiseShader2::PaintingData302     const SkBitmap& getImprovedPermutationsBitmap() const { return fImprovedPermutationsBitmap; }
303 
getGradientBitmapSkPerlinNoiseShader2::PaintingData304     const SkBitmap& getGradientBitmap() const { return fGradientBitmap; }
305 #endif
306 };
307 
MakeFractalNoise(SkScalar baseFrequencyX,SkScalar baseFrequencyY,int numOctaves,SkScalar seed,const SkISize * tileSize)308 sk_sp<SkShader> SkPerlinNoiseShader2::MakeFractalNoise(SkScalar baseFrequencyX,
309                                                        SkScalar baseFrequencyY,
310                                                        int numOctaves, SkScalar seed,
311                                                        const SkISize* tileSize) {
312     return sk_sp<SkShader>(new SkPerlinNoiseShader2(kFractalNoise_Type, baseFrequencyX,
313                                                     baseFrequencyY, numOctaves, seed, tileSize));
314 }
315 
MakeTurbulence(SkScalar baseFrequencyX,SkScalar baseFrequencyY,int numOctaves,SkScalar seed,const SkISize * tileSize)316 sk_sp<SkShader> SkPerlinNoiseShader2::MakeTurbulence(SkScalar baseFrequencyX,
317                                                      SkScalar baseFrequencyY,
318                                                      int numOctaves, SkScalar seed,
319                                                      const SkISize* tileSize) {
320     return sk_sp<SkShader>(new SkPerlinNoiseShader2(kTurbulence_Type, baseFrequencyX,
321                                                     baseFrequencyY, numOctaves, seed, tileSize));
322 }
323 
MakeImprovedNoise(SkScalar baseFrequencyX,SkScalar baseFrequencyY,int numOctaves,SkScalar z)324 sk_sp<SkShader> SkPerlinNoiseShader2::MakeImprovedNoise(SkScalar baseFrequencyX,
325                                                         SkScalar baseFrequencyY,
326                                                         int numOctaves, SkScalar z) {
327     return sk_sp<SkShader>(new SkPerlinNoiseShader2(kImprovedNoise_Type, baseFrequencyX,
328                                                     baseFrequencyY, numOctaves, z, NULL));
329 }
330 
SkPerlinNoiseShader2(SkPerlinNoiseShader2::Type type,SkScalar baseFrequencyX,SkScalar baseFrequencyY,int numOctaves,SkScalar seed,const SkISize * tileSize)331 SkPerlinNoiseShader2::SkPerlinNoiseShader2(SkPerlinNoiseShader2::Type type,
332                                          SkScalar baseFrequencyX,
333                                          SkScalar baseFrequencyY,
334                                          int numOctaves,
335                                          SkScalar seed,
336                                          const SkISize* tileSize)
337   : fType(type)
338   , fBaseFrequencyX(baseFrequencyX)
339   , fBaseFrequencyY(baseFrequencyY)
340   , fNumOctaves(numOctaves > 255 ? 255 : numOctaves/*[0,255] octaves allowed*/)
341   , fSeed(seed)
342   , fTileSize(nullptr == tileSize ? SkISize::Make(0, 0) : *tileSize)
343   , fStitchTiles(!fTileSize.isEmpty())
344 {
345     SkASSERT(numOctaves >= 0 && numOctaves < 256);
346 }
347 
~SkPerlinNoiseShader2()348 SkPerlinNoiseShader2::~SkPerlinNoiseShader2() {
349 }
350 
CreateProc(SkReadBuffer & buffer)351 sk_sp<SkFlattenable> SkPerlinNoiseShader2::CreateProc(SkReadBuffer& buffer) {
352     Type type = (Type)buffer.readInt();
353     SkScalar freqX = buffer.readScalar();
354     SkScalar freqY = buffer.readScalar();
355     int octaves = buffer.readInt();
356     SkScalar seed = buffer.readScalar();
357     SkISize tileSize;
358     tileSize.fWidth = buffer.readInt();
359     tileSize.fHeight = buffer.readInt();
360 
361     switch (type) {
362         case kFractalNoise_Type:
363             return SkPerlinNoiseShader2::MakeFractalNoise(freqX, freqY, octaves, seed, &tileSize);
364         case kTurbulence_Type:
365             return SkPerlinNoiseShader2::MakeTubulence(freqX, freqY, octaves, seed, &tileSize);
366         case kImprovedNoise_Type:
367             return SkPerlinNoiseShader2::MakeImprovedNoise(freqX, freqY, octaves, seed);
368         default:
369             return nullptr;
370     }
371 }
372 
flatten(SkWriteBuffer & buffer) const373 void SkPerlinNoiseShader2::flatten(SkWriteBuffer& buffer) const {
374     buffer.writeInt((int) fType);
375     buffer.writeScalar(fBaseFrequencyX);
376     buffer.writeScalar(fBaseFrequencyY);
377     buffer.writeInt(fNumOctaves);
378     buffer.writeScalar(fSeed);
379     buffer.writeInt(fTileSize.fWidth);
380     buffer.writeInt(fTileSize.fHeight);
381 }
382 
noise2D(int channel,const StitchData & stitchData,const SkPoint & noiseVector) const383 SkScalar SkPerlinNoiseShader2::PerlinNoiseShaderContext::noise2D(
384         int channel, const StitchData& stitchData, const SkPoint& noiseVector) const {
385     struct Noise {
386         int noisePositionIntegerValue;
387         int nextNoisePositionIntegerValue;
388         SkScalar noisePositionFractionValue;
389         Noise(SkScalar component)
390         {
391             SkScalar position = component + kPerlinNoise;
392             noisePositionIntegerValue = SkScalarFloorToInt(position);
393             noisePositionFractionValue = position - SkIntToScalar(noisePositionIntegerValue);
394             nextNoisePositionIntegerValue = noisePositionIntegerValue + 1;
395         }
396     };
397     Noise noiseX(noiseVector.x());
398     Noise noiseY(noiseVector.y());
399     SkScalar u, v;
400     const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
401     // If stitching, adjust lattice points accordingly.
402     if (perlinNoiseShader.fStitchTiles) {
403         noiseX.noisePositionIntegerValue =
404             checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
405         noiseY.noisePositionIntegerValue =
406             checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
407         noiseX.nextNoisePositionIntegerValue =
408             checkNoise(noiseX.nextNoisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
409         noiseY.nextNoisePositionIntegerValue =
410             checkNoise(noiseY.nextNoisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
411     }
412     noiseX.noisePositionIntegerValue &= kBlockMask;
413     noiseY.noisePositionIntegerValue &= kBlockMask;
414     noiseX.nextNoisePositionIntegerValue &= kBlockMask;
415     noiseY.nextNoisePositionIntegerValue &= kBlockMask;
416     int i =
417         fPaintingData->fLatticeSelector[noiseX.noisePositionIntegerValue];
418     int j =
419         fPaintingData->fLatticeSelector[noiseX.nextNoisePositionIntegerValue];
420     int b00 = (i + noiseY.noisePositionIntegerValue) & kBlockMask;
421     int b10 = (j + noiseY.noisePositionIntegerValue) & kBlockMask;
422     int b01 = (i + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
423     int b11 = (j + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
424     SkScalar sx = smoothCurve(noiseX.noisePositionFractionValue);
425     SkScalar sy = smoothCurve(noiseY.noisePositionFractionValue);
426     // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement
427     SkPoint fractionValue = SkPoint::Make(noiseX.noisePositionFractionValue,
428                                           noiseY.noisePositionFractionValue); // Offset (0,0)
429     u = fPaintingData->fGradient[channel][b00].dot(fractionValue);
430     fractionValue.fX -= SK_Scalar1; // Offset (-1,0)
431     v = fPaintingData->fGradient[channel][b10].dot(fractionValue);
432     SkScalar a = SkScalarInterp(u, v, sx);
433     fractionValue.fY -= SK_Scalar1; // Offset (-1,-1)
434     v = fPaintingData->fGradient[channel][b11].dot(fractionValue);
435     fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1)
436     u = fPaintingData->fGradient[channel][b01].dot(fractionValue);
437     SkScalar b = SkScalarInterp(u, v, sx);
438     return SkScalarInterp(a, b, sy);
439 }
440 
calculateTurbulenceValueForPoint(int channel,StitchData & stitchData,const SkPoint & point) const441 SkScalar SkPerlinNoiseShader2::PerlinNoiseShaderContext::calculateTurbulenceValueForPoint(
442         int channel, StitchData& stitchData, const SkPoint& point) const {
443     const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
444     if (perlinNoiseShader.fStitchTiles) {
445         // Set up TurbulenceInitial stitch values.
446         stitchData = fPaintingData->fStitchDataInit;
447     }
448     SkScalar turbulenceFunctionResult = 0;
449     SkPoint noiseVector(SkPoint::Make(point.x() * fPaintingData->fBaseFrequency.fX,
450                                       point.y() * fPaintingData->fBaseFrequency.fY));
451     SkScalar ratio = SK_Scalar1;
452     for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) {
453         SkScalar noise = noise2D(channel, stitchData, noiseVector);
454         SkScalar numer = (perlinNoiseShader.fType == kFractalNoise_Type) ?
455                             noise : SkScalarAbs(noise);
456         turbulenceFunctionResult += numer / ratio;
457         noiseVector.fX *= 2;
458         noiseVector.fY *= 2;
459         ratio *= 2;
460         if (perlinNoiseShader.fStitchTiles) {
461             // Update stitch values
462             stitchData.fWidth  *= 2;
463             stitchData.fWrapX   = stitchData.fWidth + kPerlinNoise;
464             stitchData.fHeight *= 2;
465             stitchData.fWrapY   = stitchData.fHeight + kPerlinNoise;
466         }
467     }
468 
469     // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
470     // by fractalNoise and (turbulenceFunctionResult) by turbulence.
471     if (perlinNoiseShader.fType == kFractalNoise_Type) {
472         turbulenceFunctionResult = SkScalarHalf(turbulenceFunctionResult + 1);
473     }
474 
475     if (channel == 3) { // Scale alpha by paint value
476         turbulenceFunctionResult *= SkIntToScalar(getPaintAlpha()) / 255;
477     }
478 
479     // Clamp result
480     return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1);
481 }
482 
483 ////////////////////////////////////////////////////////////////////////////////////////////////////
484 // Improved Perlin Noise based on Java implementation found at http://mrl.nyu.edu/~perlin/noise/
fade(SkScalar t)485 static SkScalar fade(SkScalar t) {
486     return t * t * t * (t * (t * 6 - 15) + 10);
487 }
488 
lerp(SkScalar t,SkScalar a,SkScalar b)489 static SkScalar lerp(SkScalar t, SkScalar a, SkScalar b) {
490     return a + t * (b - a);
491 }
492 
grad(int hash,SkScalar x,SkScalar y,SkScalar z)493 static SkScalar grad(int hash, SkScalar x, SkScalar y, SkScalar z) {
494     int h = hash & 15;
495     SkScalar u = h < 8 ? x : y;
496     SkScalar v = h < 4 ? y : h == 12 || h == 14 ? x : z;
497     return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
498 }
499 
calculateImprovedNoiseValueForPoint(int channel,const SkPoint & point) const500 SkScalar SkPerlinNoiseShader2::PerlinNoiseShaderContext::calculateImprovedNoiseValueForPoint(
501         int channel, const SkPoint& point) const {
502     const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
503     SkScalar x = point.fX * perlinNoiseShader.fBaseFrequencyX;
504     SkScalar y = point.fY * perlinNoiseShader.fBaseFrequencyY;
505     // z offset between different channels, chosen arbitrarily
506     static const SkScalar CHANNEL_DELTA = 1000.0f;
507     SkScalar z = channel * CHANNEL_DELTA + perlinNoiseShader.fSeed;
508     SkScalar result = 0;
509     SkScalar ratio = SK_Scalar1;
510     for (int i = 0; i < perlinNoiseShader.fNumOctaves; i++) {
511         int X = SkScalarFloorToInt(x) & 255;
512         int Y = SkScalarFloorToInt(y) & 255;
513         int Z = SkScalarFloorToInt(z) & 255;
514         SkScalar px = x - SkScalarFloorToScalar(x);
515         SkScalar py = y - SkScalarFloorToScalar(y);
516         SkScalar pz = z - SkScalarFloorToScalar(z);
517         SkScalar u = fade(px);
518         SkScalar v = fade(py);
519         SkScalar w = fade(pz);
520         uint8_t* permutations = improved_noise_permutations;
521         int A  = permutations[X] + Y;
522         int AA = permutations[A] + Z;
523         int AB = permutations[A + 1] + Z;
524         int B  = permutations[X + 1] + Y;
525         int BA = permutations[B] + Z;
526         int BB = permutations[B + 1] + Z;
527         result += lerp(w, lerp(v, lerp(u, grad(permutations[AA    ], px    , py    , pz    ),
528                                           grad(permutations[BA    ], px - 1, py    , pz    )),
529                                   lerp(u, grad(permutations[AB    ], px    , py - 1, pz    ),
530                                           grad(permutations[BB    ], px - 1, py - 1, pz    ))),
531                           lerp(v, lerp(u, grad(permutations[AA + 1], px    , py    , pz - 1),
532                                           grad(permutations[BA + 1], px - 1, py    , pz - 1)),
533                                   lerp(u, grad(permutations[AB + 1], px    , py - 1, pz - 1),
534                                           grad(permutations[BB + 1], px - 1, py - 1, pz - 1)))) /
535                    ratio;
536         x *= 2;
537         y *= 2;
538         ratio *= 2;
539     }
540     result = SkScalarClampMax((result + 1.0f) / 2.0f, 1.0f);
541     return result;
542 }
543 ////////////////////////////////////////////////////////////////////////////////////////////////////
544 
shade(const SkPoint & point,StitchData & stitchData) const545 SkPMColor SkPerlinNoiseShader2::PerlinNoiseShaderContext::shade(
546         const SkPoint& point, StitchData& stitchData) const {
547     const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
548     SkPoint newPoint;
549     fMatrix.mapPoints(&newPoint, &point, 1);
550     newPoint.fX = SkScalarRoundToScalar(newPoint.fX);
551     newPoint.fY = SkScalarRoundToScalar(newPoint.fY);
552 
553     U8CPU rgba[4];
554     for (int channel = 3; channel >= 0; --channel) {
555         SkScalar value;
556         if (perlinNoiseShader.fType == kImprovedNoise_Type) {
557             value = calculateImprovedNoiseValueForPoint(channel, newPoint);
558         }
559         else {
560             value = calculateTurbulenceValueForPoint(channel, stitchData, newPoint);
561         }
562         rgba[channel] = SkScalarFloorToInt(255 * value);
563     }
564     return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]);
565 }
566 
onMakeContext(const ContextRec & rec,SkArenaAlloc * alloc) const567 SkShader::Context* SkPerlinNoiseShader2::onMakeContext(const ContextRec& rec,
568                                                        SkArenaAlloc* alloc) const {
569     return alloc->make<PerlinNoiseShaderContext>(*this, rec);
570 }
571 
PerlinNoiseShaderContext(const SkPerlinNoiseShader2 & shader,const ContextRec & rec)572 SkPerlinNoiseShader2::PerlinNoiseShaderContext::PerlinNoiseShaderContext(
573         const SkPerlinNoiseShader2& shader, const ContextRec& rec)
574     : INHERITED(shader, rec)
575 {
576     SkMatrix newMatrix = *rec.fMatrix;
577     newMatrix.preConcat(shader.getLocalMatrix());
578     if (rec.fLocalMatrix) {
579         newMatrix.preConcat(*rec.fLocalMatrix);
580     }
581     // This (1,1) translation is due to WebKit's 1 based coordinates for the noise
582     // (as opposed to 0 based, usually). The same adjustment is in the setData() function.
583     fMatrix.setTranslate(-newMatrix.getTranslateX() + SK_Scalar1, -newMatrix.getTranslateY() + SK_Scalar1);
584     fPaintingData = new PaintingData(shader.fTileSize, shader.fSeed, shader.fBaseFrequencyX,
585                                      shader.fBaseFrequencyY, newMatrix);
586 }
587 
~PerlinNoiseShaderContext()588 SkPerlinNoiseShader2::PerlinNoiseShaderContext::~PerlinNoiseShaderContext() { delete fPaintingData; }
589 
shadeSpan(int x,int y,SkPMColor result[],int count)590 void SkPerlinNoiseShader2::PerlinNoiseShaderContext::shadeSpan(
591         int x, int y, SkPMColor result[], int count) {
592     SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
593     StitchData stitchData;
594     for (int i = 0; i < count; ++i) {
595         result[i] = shade(point, stitchData);
596         point.fX += SK_Scalar1;
597     }
598 }
599 
600 /////////////////////////////////////////////////////////////////////
601 
602 #if SK_SUPPORT_GPU
603 
604 class GrGLPerlinNoise2 : public GrGLSLFragmentProcessor {
605 public:
606     void emitCode(EmitArgs&) override;
607 
608     static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder* b);
609 
610 protected:
611     void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
612 
613 private:
614     GrGLSLProgramDataManager::UniformHandle fStitchDataUni;
615     GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
616 
617     typedef GrGLSLFragmentProcessor INHERITED;
618 };
619 
620 /////////////////////////////////////////////////////////////////////
621 
622 class GrPerlinNoise2Effect : public GrFragmentProcessor {
623 public:
Make(GrResourceProvider * resourceProvider,SkPerlinNoiseShader2::Type type,int numOctaves,bool stitchTiles,SkPerlinNoiseShader2::PaintingData * paintingData,sk_sp<GrTextureProxy> permutationsProxy,sk_sp<GrTextureProxy> noiseProxy,const SkMatrix & matrix)624     static sk_sp<GrFragmentProcessor> Make(GrResourceProvider* resourceProvider,
625                                            SkPerlinNoiseShader2::Type type,
626                                            int numOctaves, bool stitchTiles,
627                                            SkPerlinNoiseShader2::PaintingData* paintingData,
628                                            sk_sp<GrTextureProxy> permutationsProxy,
629                                            sk_sp<GrTextureProxy> noiseProxy,
630                                            const SkMatrix& matrix) {
631         return sk_sp<GrFragmentProcessor>(
632             new GrPerlinNoise2Effect(resourceProvider, type, numOctaves, stitchTiles, paintingData,
633                                      std::move(permutationsProxy), std::move(noiseProxy), matrix));
634     }
635 
~GrPerlinNoise2Effect()636     ~GrPerlinNoise2Effect() override { delete fPaintingData; }
637 
name() const638     const char* name() const override { return "PerlinNoise"; }
639 
stitchData() const640     const SkPerlinNoiseShader2::StitchData& stitchData() const { return fPaintingData->fStitchDataInit; }
641 
type() const642     SkPerlinNoiseShader2::Type type() const { return fType; }
stitchTiles() const643     bool stitchTiles() const { return fStitchTiles; }
baseFrequency() const644     const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
numOctaves() const645     int numOctaves() const { return fNumOctaves; }
matrix() const646     const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
647 
648 private:
onCreateGLSLInstance() const649     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
650         return new GrGLPerlinNoise2;
651     }
652 
onGetGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const653     virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps,
654                                        GrProcessorKeyBuilder* b) const override {
655         GrGLPerlinNoise2::GenKey(*this, caps, b);
656     }
657 
onIsEqual(const GrFragmentProcessor & sBase) const658     bool onIsEqual(const GrFragmentProcessor& sBase) const override {
659         const GrPerlinNoise2Effect& s = sBase.cast<GrPerlinNoise2Effect>();
660         return fType == s.fType &&
661                fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency &&
662                fNumOctaves == s.fNumOctaves &&
663                fStitchTiles == s.fStitchTiles &&
664                fPaintingData->fStitchDataInit == s.fPaintingData->fStitchDataInit;
665     }
666 
GrPerlinNoise2Effect(GrResourceProvider * resourceProvider,SkPerlinNoiseShader2::Type type,int numOctaves,bool stitchTiles,SkPerlinNoiseShader2::PaintingData * paintingData,sk_sp<GrTextureProxy> permutationsProxy,sk_sp<GrTextureProxy> noiseProxy,const SkMatrix & matrix)667     GrPerlinNoise2Effect(GrResourceProvider* resourceProvider,
668                          SkPerlinNoiseShader2::Type type, int numOctaves, bool stitchTiles,
669                          SkPerlinNoiseShader2::PaintingData* paintingData,
670                          sk_sp<GrTextureProxy> permutationsProxy,
671                          sk_sp<GrTextureProxy> noiseProxy,
672                          const SkMatrix& matrix)
673             : INHERITED(kNone_OptimizationFlags)
674             , fType(type)
675             , fNumOctaves(numOctaves)
676             , fStitchTiles(stitchTiles)
677             , fPermutationsSampler(resourceProvider, std::move(permutationsProxy))
678             , fNoiseSampler(resourceProvider, std::move(noiseProxy))
679             , fPaintingData(paintingData) {
680         this->initClassID<GrPerlinNoise2Effect>();
681         this->addTextureSampler(&fPermutationsSampler);
682         this->addTextureSampler(&fNoiseSampler);
683         fCoordTransform.reset(matrix);
684         this->addCoordTransform(&fCoordTransform);
685     }
686 
687     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
688 
689     SkPerlinNoiseShader2::Type          fType;
690     GrCoordTransform                    fCoordTransform;
691     int                                 fNumOctaves;
692     bool                                fStitchTiles;
693     TextureSampler                      fPermutationsSampler;
694     TextureSampler                      fNoiseSampler;
695     SkPerlinNoiseShader2::PaintingData* fPaintingData;
696 
697     typedef GrFragmentProcessor INHERITED;
698 };
699 
700 /////////////////////////////////////////////////////////////////////
701 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrPerlinNoise2Effect);
702 
703 #if GR_TEST_UTILS
TestCreate(GrProcessorTestData * d)704 sk_sp<GrFragmentProcessor> GrPerlinNoise2Effect::TestCreate(GrProcessorTestData* d) {
705     int      numOctaves = d->fRandom->nextRangeU(2, 10);
706     bool     stitchTiles = d->fRandom->nextBool();
707     SkScalar seed = SkIntToScalar(d->fRandom->nextU());
708     SkISize  tileSize = SkISize::Make(d->fRandom->nextRangeU(4, 4096),
709                                       d->fRandom->nextRangeU(4, 4096));
710     SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
711                                                           0.99f);
712     SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
713                                                           0.99f);
714 
715     sk_sp<SkShader> shader(d->fRandom->nextBool() ?
716         SkPerlinNoiseShader2::MakeFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves, seed,
717                                                stitchTiles ? &tileSize : nullptr) :
718         SkPerlinNoiseShader2::MakeTurbulence(baseFrequencyX, baseFrequencyY, numOctaves, seed,
719                                              stitchTiles ? &tileSize : nullptr));
720 
721     GrTest::TestAsFPArgs asFPArgs(d);
722     return shader->asFragmentProcessor(asFPArgs.args());
723 }
724 #endif
725 
emitCode(EmitArgs & args)726 void GrGLPerlinNoise2::emitCode(EmitArgs& args) {
727     const GrPerlinNoise2Effect& pne = args.fFp.cast<GrPerlinNoise2Effect>();
728 
729     GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
730     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
731     SkString vCoords = fsBuilder->ensureCoords2D(args.fTransformedCoords[0]);
732 
733     fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
734                                                    kVec2f_GrSLType, kDefault_GrSLPrecision,
735                                                    "baseFrequency");
736     const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
737 
738     const char* stitchDataUni = nullptr;
739     if (pne.stitchTiles()) {
740         fStitchDataUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
741                                                     kVec2f_GrSLType, kDefault_GrSLPrecision,
742                                                     "stitchData");
743         stitchDataUni = uniformHandler->getUniformCStr(fStitchDataUni);
744     }
745 
746     // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8
747     const char* chanCoordR  = "0.125";
748     const char* chanCoordG  = "0.375";
749     const char* chanCoordB  = "0.625";
750     const char* chanCoordA  = "0.875";
751     const char* chanCoord   = "chanCoord";
752     const char* stitchData  = "stitchData";
753     const char* ratio       = "ratio";
754     const char* noiseVec    = "noiseVec";
755     const char* noiseSmooth = "noiseSmooth";
756     const char* floorVal    = "floorVal";
757     const char* fractVal    = "fractVal";
758     const char* uv          = "uv";
759     const char* ab          = "ab";
760     const char* latticeIdx  = "latticeIdx";
761     const char* bcoords     = "bcoords";
762     const char* lattice     = "lattice";
763     const char* inc8bit     = "0.00390625";  // 1.0 / 256.0
764     // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a
765     // [-1,1] vector and perform a dot product between that vector and the provided vector.
766     const char* dotLattice  = "dot(((%s.ga + %s.rb * vec2(%s)) * vec2(2.0) - vec2(1.0)), %s);";
767 
768     // Add noise function
769     static const GrShaderVar gPerlinNoiseArgs[] =  {
770         GrShaderVar(chanCoord, kFloat_GrSLType),
771         GrShaderVar(noiseVec, kVec2f_GrSLType)
772     };
773 
774     static const GrShaderVar gPerlinNoiseStitchArgs[] =  {
775         GrShaderVar(chanCoord, kFloat_GrSLType),
776         GrShaderVar(noiseVec, kVec2f_GrSLType),
777         GrShaderVar(stitchData, kVec2f_GrSLType)
778     };
779 
780     SkString noiseCode;
781 
782     noiseCode.appendf("\tvec4 %s;\n", floorVal);
783     noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec);
784     noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal);
785     noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec);
786 
787     // smooth curve : t * t * (3 - 2 * t)
788     noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);",
789         noiseSmooth, fractVal, fractVal, fractVal);
790 
791     // Adjust frequencies if we're stitching tiles
792     if (pne.stitchTiles()) {
793         noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }",
794             floorVal, stitchData, floorVal, stitchData);
795         noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }",
796             floorVal, stitchData, floorVal, stitchData);
797         noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }",
798             floorVal, stitchData, floorVal, stitchData);
799         noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }",
800             floorVal, stitchData, floorVal, stitchData);
801     }
802 
803     // Get texture coordinates and normalize
804     noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / vec4(256.0));\n",
805         floorVal, floorVal);
806 
807     // Get permutation for x
808     {
809         SkString xCoords("");
810         xCoords.appendf("vec2(%s.x, 0.5)", floorVal);
811 
812         noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
813         fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
814                                        kVec2f_GrSLType);
815         noiseCode.append(".r;");
816     }
817 
818     // Get permutation for x + 1
819     {
820         SkString xCoords("");
821         xCoords.appendf("vec2(%s.z, 0.5)", floorVal);
822 
823         noiseCode.appendf("\n\t%s.y = ", latticeIdx);
824         fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
825                                        kVec2f_GrSLType);
826         noiseCode.append(".r;");
827     }
828 
829 #if defined(SK_BUILD_FOR_ANDROID)
830     // Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3).
831     // The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit
832     // value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725
833     // (or 0.484368 here). The following rounding operation prevents these precision issues from
834     // affecting the result of the noise by making sure that we only have multiples of 1/255.
835     // (Note that 1/255 is about 0.003921569, which is the value used here).
836     noiseCode.appendf("\n\t%s = floor(%s * vec2(255.0) + vec2(0.5)) * vec2(0.003921569);",
837                       latticeIdx, latticeIdx);
838 #endif
839 
840     // Get (x,y) coordinates with the permutated x
841     noiseCode.appendf("\n\tvec4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal);
842 
843     noiseCode.appendf("\n\n\tvec2 %s;", uv);
844     // Compute u, at offset (0,0)
845     {
846         SkString latticeCoords("");
847         latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord);
848         noiseCode.appendf("\n\tvec4 %s = ", lattice);
849         fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
850             kVec2f_GrSLType);
851         noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
852         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
853     }
854 
855     noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal);
856     // Compute v, at offset (-1,0)
857     {
858         SkString latticeCoords("");
859         latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord);
860         noiseCode.append("\n\tlattice = ");
861         fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
862             kVec2f_GrSLType);
863         noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
864         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
865     }
866 
867     // Compute 'a' as a linear interpolation of 'u' and 'v'
868     noiseCode.appendf("\n\tvec2 %s;", ab);
869     noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
870 
871     noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal);
872     // Compute v, at offset (-1,-1)
873     {
874         SkString latticeCoords("");
875         latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord);
876         noiseCode.append("\n\tlattice = ");
877         fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
878             kVec2f_GrSLType);
879         noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
880         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
881     }
882 
883     noiseCode.appendf("\n\t%s.x += 1.0;", fractVal);
884     // Compute u, at offset (0,-1)
885     {
886         SkString latticeCoords("");
887         latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord);
888         noiseCode.append("\n\tlattice = ");
889         fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
890             kVec2f_GrSLType);
891         noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
892         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
893     }
894 
895     // Compute 'b' as a linear interpolation of 'u' and 'v'
896     noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
897     // Compute the noise as a linear interpolation of 'a' and 'b'
898     noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth);
899 
900     SkString noiseFuncName;
901     if (pne.stitchTiles()) {
902         fsBuilder->emitFunction(kFloat_GrSLType,
903                                 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs),
904                                 gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName);
905     } else {
906         fsBuilder->emitFunction(kFloat_GrSLType,
907                                 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs),
908                                 gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName);
909     }
910 
911     // There are rounding errors if the floor operation is not performed here
912     fsBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;",
913                            noiseVec, vCoords.c_str(), baseFrequencyUni);
914 
915     // Clear the color accumulator
916     fsBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", args.fOutputColor);
917 
918     if (pne.stitchTiles()) {
919         // Set up TurbulenceInitial stitch values.
920         fsBuilder->codeAppendf("\n\t\tvec2 %s = %s;", stitchData, stitchDataUni);
921     }
922 
923     fsBuilder->codeAppendf("\n\t\tfloat %s = 1.0;", ratio);
924 
925     // Loop over all octaves
926     fsBuilder->codeAppendf("for (int octave = 0; octave < %d; ++octave) {", pne.numOctaves());
927 
928     fsBuilder->codeAppendf("\n\t\t\t%s += ", args.fOutputColor);
929     if (pne.type() != SkPerlinNoiseShader2::kFractalNoise_Type) {
930         fsBuilder->codeAppend("abs(");
931     }
932     if (pne.stitchTiles()) {
933         fsBuilder->codeAppendf(
934             "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s),"
935                  "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))",
936             noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData,
937             noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData,
938             noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData,
939             noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData);
940     } else {
941         fsBuilder->codeAppendf(
942             "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s),"
943                  "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))",
944             noiseFuncName.c_str(), chanCoordR, noiseVec,
945             noiseFuncName.c_str(), chanCoordG, noiseVec,
946             noiseFuncName.c_str(), chanCoordB, noiseVec,
947             noiseFuncName.c_str(), chanCoordA, noiseVec);
948     }
949     if (pne.type() != SkPerlinNoiseShader2::kFractalNoise_Type) {
950         fsBuilder->codeAppendf(")"); // end of "abs("
951     }
952     fsBuilder->codeAppendf(" * %s;", ratio);
953 
954     fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec);
955     fsBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio);
956 
957     if (pne.stitchTiles()) {
958         fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData);
959     }
960     fsBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves
961 
962     if (pne.type() == SkPerlinNoiseShader2::kFractalNoise_Type) {
963         // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
964         // by fractalNoise and (turbulenceFunctionResult) by turbulence.
965         fsBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);",
966                                args.fOutputColor,args.fOutputColor);
967     }
968 
969     // Clamp values
970     fsBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
971 
972     // Pre-multiply the result
973     fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
974                            args.fOutputColor, args.fOutputColor,
975                            args.fOutputColor, args.fOutputColor);
976 }
977 
GenKey(const GrProcessor & processor,const GrShaderCaps &,GrProcessorKeyBuilder * b)978 void GrGLPerlinNoise2::GenKey(const GrProcessor& processor, const GrShaderCaps&,
979                               GrProcessorKeyBuilder* b) {
980     const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
981 
982     uint32_t key = turbulence.numOctaves();
983 
984     key = key << 3; // Make room for next 3 bits
985 
986     switch (turbulence.type()) {
987         case SkPerlinNoiseShader2::kFractalNoise_Type:
988             key |= 0x1;
989             break;
990         case SkPerlinNoiseShader2::kTurbulence_Type:
991             key |= 0x2;
992             break;
993         default:
994             // leave key at 0
995             break;
996     }
997 
998     if (turbulence.stitchTiles()) {
999         key |= 0x4; // Flip the 3rd bit if tile stitching is on
1000     }
1001 
1002     b->add32(key);
1003 }
1004 
onSetData(const GrGLSLProgramDataManager & pdman,const GrProcessor & processor)1005 void GrGLPerlinNoise2::onSetData(const GrGLSLProgramDataManager& pdman,
1006                                 const GrProcessor& processor) {
1007     INHERITED::onSetData(pdman, processor);
1008 
1009     const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
1010 
1011     const SkVector& baseFrequency = turbulence.baseFrequency();
1012     pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1013 
1014     if (turbulence.stitchTiles()) {
1015         const SkPerlinNoiseShader2::StitchData& stitchData = turbulence.stitchData();
1016         pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth),
1017                                    SkIntToScalar(stitchData.fHeight));
1018     }
1019 }
1020 
1021 /////////////////////////////////////////////////////////////////////
1022 
1023 class GrGLImprovedPerlinNoise : public GrGLSLFragmentProcessor {
1024 public:
1025     void emitCode(EmitArgs&) override;
1026 
1027     static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
1028 
1029 protected:
1030     void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
1031 
1032 private:
1033     GrGLSLProgramDataManager::UniformHandle fZUni;
1034     GrGLSLProgramDataManager::UniformHandle fOctavesUni;
1035     GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
1036 
1037     typedef GrGLSLFragmentProcessor INHERITED;
1038 };
1039 
1040 /////////////////////////////////////////////////////////////////////
1041 
1042 class GrImprovedPerlinNoiseEffect : public GrFragmentProcessor {
1043 public:
Make(GrResourceProvider * resourceProvider,int octaves,SkScalar z,SkPerlinNoiseShader2::PaintingData * paintingData,sk_sp<GrTextureProxy> permutationsProxy,sk_sp<GrTextureProxy> gradientProxy,const SkMatrix & matrix)1044     static sk_sp<GrFragmentProcessor> Make(GrResourceProvider* resourceProvider,
1045                                            int octaves, SkScalar z,
1046                                            SkPerlinNoiseShader2::PaintingData* paintingData,
1047                                            sk_sp<GrTextureProxy> permutationsProxy,
1048                                            sk_sp<GrTextureProxy> gradientProxy,
1049                                            const SkMatrix& matrix) {
1050         return sk_sp<GrFragmentProcessor>(
1051             new GrImprovedPerlinNoiseEffect(resourceProvider, octaves, z, paintingData,
1052                                             std::move(permutationsProxy),
1053                                             std::move(gradientProxy), matrix));
1054     }
1055 
~GrImprovedPerlinNoiseEffect()1056     ~GrImprovedPerlinNoiseEffect() override { delete fPaintingData; }
1057 
name() const1058     const char* name() const override { return "ImprovedPerlinNoise"; }
1059 
baseFrequency() const1060     const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
z() const1061     SkScalar z() const { return fZ; }
octaves() const1062     int octaves() const { return fOctaves; }
matrix() const1063     const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
1064 
1065 private:
onCreateGLSLInstance() const1066     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
1067         return new GrGLImprovedPerlinNoise;
1068     }
1069 
onGetGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const1070     void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
1071         GrGLImprovedPerlinNoise::GenKey(*this, caps, b);
1072     }
1073 
onIsEqual(const GrFragmentProcessor & sBase) const1074     bool onIsEqual(const GrFragmentProcessor& sBase) const override {
1075         const GrImprovedPerlinNoiseEffect& s = sBase.cast<GrImprovedPerlinNoiseEffect>();
1076         return fZ == fZ &&
1077                fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency;
1078     }
1079 
GrImprovedPerlinNoiseEffect(GrResourceProvider * resourceProvider,int octaves,SkScalar z,SkPerlinNoiseShader2::PaintingData * paintingData,sk_sp<GrTextureProxy> permutationsProxy,sk_sp<GrTextureProxy> gradientProxy,const SkMatrix & matrix)1080     GrImprovedPerlinNoiseEffect(GrResourceProvider* resourceProvider,
1081                                 int octaves, SkScalar z,
1082                                 SkPerlinNoiseShader2::PaintingData* paintingData,
1083                                 sk_sp<GrTextureProxy> permutationsProxy,
1084                                 sk_sp<GrTextureProxy> gradientProxy,
1085                                 const SkMatrix& matrix)
1086             : INHERITED(kNone_OptimizationFlags)
1087             , fOctaves(octaves)
1088             , fZ(z)
1089             , fPermutationsSampler(resourceProvider, std::move(permutationsProxy))
1090             , fGradientSampler(resourceProvider, std::move(gradientProxy))
1091             , fPaintingData(paintingData) {
1092         this->initClassID<GrImprovedPerlinNoiseEffect>();
1093         this->addTextureSampler(&fPermutationsSampler);
1094         this->addTextureSampler(&fGradientSampler);
1095         fCoordTransform.reset(matrix);
1096         this->addCoordTransform(&fCoordTransform);
1097     }
1098 
1099     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
1100 
1101     GrCoordTransform                    fCoordTransform;
1102     int                                 fOctaves;
1103     SkScalar                            fZ;
1104     TextureSampler                      fPermutationsSampler;
1105     TextureSampler                      fGradientSampler;
1106     SkPerlinNoiseShader2::PaintingData* fPaintingData;
1107 
1108     typedef GrFragmentProcessor INHERITED;
1109 };
1110 
1111 /////////////////////////////////////////////////////////////////////
1112 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrImprovedPerlinNoiseEffect);
1113 
1114 #if GR_TEST_UTILS
TestCreate(GrProcessorTestData * d)1115 sk_sp<GrFragmentProcessor> GrImprovedPerlinNoiseEffect::TestCreate(GrProcessorTestData* d) {
1116     SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
1117                                                           0.99f);
1118     SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
1119                                                           0.99f);
1120     int numOctaves = d->fRandom->nextRangeU(2, 10);
1121     SkScalar z = SkIntToScalar(d->fRandom->nextU());
1122 
1123     sk_sp<SkShader> shader(SkPerlinNoiseShader2::MakeImprovedNoise(baseFrequencyX,
1124                                                                    baseFrequencyY,
1125                                                                    numOctaves,
1126                                                                    z));
1127 
1128     GrTest::TestAsFPArgs asFPArgs(d);
1129     return shader->asFragmentProcessor(asFPArgs.args());
1130 }
1131 #endif
1132 
emitCode(EmitArgs & args)1133 void GrGLImprovedPerlinNoise::emitCode(EmitArgs& args) {
1134     GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
1135     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
1136     SkString vCoords = fsBuilder->ensureCoords2D(args.fTransformedCoords[0]);
1137 
1138     fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
1139                                                    kVec2f_GrSLType, kDefault_GrSLPrecision,
1140                                                    "baseFrequency");
1141     const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
1142 
1143     fOctavesUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
1144                                              kFloat_GrSLType, kDefault_GrSLPrecision,
1145                                              "octaves");
1146     const char* octavesUni = uniformHandler->getUniformCStr(fOctavesUni);
1147 
1148     fZUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
1149                                        kFloat_GrSLType, kDefault_GrSLPrecision,
1150                                        "z");
1151     const char* zUni = uniformHandler->getUniformCStr(fZUni);
1152 
1153     // fade function
1154     static const GrShaderVar fadeArgs[] =  {
1155         GrShaderVar("t", kVec3f_GrSLType)
1156     };
1157     SkString fadeFuncName;
1158     fsBuilder->emitFunction(kVec3f_GrSLType, "fade", SK_ARRAY_COUNT(fadeArgs),
1159                             fadeArgs,
1160                             "return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);",
1161                             &fadeFuncName);
1162 
1163     // perm function
1164     static const GrShaderVar permArgs[] =  {
1165         GrShaderVar("x", kFloat_GrSLType)
1166     };
1167     SkString permFuncName;
1168     SkString permCode("return ");
1169     // FIXME even though I'm creating these textures with kRepeat_TileMode, they're clamped. Not
1170     // sure why. Using fract() (here and the next texture lookup) as a workaround.
1171     fsBuilder->appendTextureLookup(&permCode, args.fTexSamplers[0], "vec2(fract(x / 256.0), 0.0)",
1172                                    kVec2f_GrSLType);
1173     permCode.append(".r * 255.0;");
1174     fsBuilder->emitFunction(kFloat_GrSLType, "perm", SK_ARRAY_COUNT(permArgs), permArgs,
1175                             permCode.c_str(), &permFuncName);
1176 
1177     // grad function
1178     static const GrShaderVar gradArgs[] =  {
1179         GrShaderVar("x", kFloat_GrSLType),
1180         GrShaderVar("p", kVec3f_GrSLType)
1181     };
1182     SkString gradFuncName;
1183     SkString gradCode("return dot(");
1184     fsBuilder->appendTextureLookup(&gradCode, args.fTexSamplers[1], "vec2(fract(x / 16.0), 0.0)",
1185                                    kVec2f_GrSLType);
1186     gradCode.append(".rgb * 255.0 - vec3(1.0), p);");
1187     fsBuilder->emitFunction(kFloat_GrSLType, "grad", SK_ARRAY_COUNT(gradArgs), gradArgs,
1188                             gradCode.c_str(), &gradFuncName);
1189 
1190     // lerp function
1191     static const GrShaderVar lerpArgs[] =  {
1192         GrShaderVar("a", kFloat_GrSLType),
1193         GrShaderVar("b", kFloat_GrSLType),
1194         GrShaderVar("w", kFloat_GrSLType)
1195     };
1196     SkString lerpFuncName;
1197     fsBuilder->emitFunction(kFloat_GrSLType, "lerp", SK_ARRAY_COUNT(lerpArgs), lerpArgs,
1198                             "return a + w * (b - a);", &lerpFuncName);
1199 
1200     // noise function
1201     static const GrShaderVar noiseArgs[] =  {
1202         GrShaderVar("p", kVec3f_GrSLType),
1203     };
1204     SkString noiseFuncName;
1205     SkString noiseCode;
1206     noiseCode.append("vec3 P = mod(floor(p), 256.0);");
1207     noiseCode.append("p -= floor(p);");
1208     noiseCode.appendf("vec3 f = %s(p);", fadeFuncName.c_str());
1209     noiseCode.appendf("float A = %s(P.x) + P.y;", permFuncName.c_str());
1210     noiseCode.appendf("float AA = %s(A) + P.z;", permFuncName.c_str());
1211     noiseCode.appendf("float AB = %s(A + 1.0) + P.z;", permFuncName.c_str());
1212     noiseCode.appendf("float B =  %s(P.x + 1.0) + P.y;", permFuncName.c_str());
1213     noiseCode.appendf("float BA = %s(B) + P.z;", permFuncName.c_str());
1214     noiseCode.appendf("float BB = %s(B + 1.0) + P.z;", permFuncName.c_str());
1215     noiseCode.appendf("float result = %s(", lerpFuncName.c_str());
1216     noiseCode.appendf("%s(%s(%s(%s(AA), p),", lerpFuncName.c_str(), lerpFuncName.c_str(),
1217                       gradFuncName.c_str(), permFuncName.c_str());
1218     noiseCode.appendf("%s(%s(BA), p + vec3(-1.0, 0.0, 0.0)), f.x),", gradFuncName.c_str(),
1219                       permFuncName.c_str());
1220     noiseCode.appendf("%s(%s(%s(AB), p + vec3(0.0, -1.0, 0.0)),", lerpFuncName.c_str(),
1221                       gradFuncName.c_str(), permFuncName.c_str());
1222     noiseCode.appendf("%s(%s(BB), p + vec3(-1.0, -1.0, 0.0)), f.x), f.y),",
1223                       gradFuncName.c_str(), permFuncName.c_str());
1224     noiseCode.appendf("%s(%s(%s(%s(AA + 1.0), p + vec3(0.0, 0.0, -1.0)),",
1225                       lerpFuncName.c_str(), lerpFuncName.c_str(), gradFuncName.c_str(),
1226                       permFuncName.c_str());
1227     noiseCode.appendf("%s(%s(BA + 1.0), p + vec3(-1.0, 0.0, -1.0)), f.x),",
1228                       gradFuncName.c_str(), permFuncName.c_str());
1229     noiseCode.appendf("%s(%s(%s(AB + 1.0), p + vec3(0.0, -1.0, -1.0)),",
1230                       lerpFuncName.c_str(), gradFuncName.c_str(), permFuncName.c_str());
1231     noiseCode.appendf("%s(%s(BB + 1.0), p + vec3(-1.0, -1.0, -1.0)), f.x), f.y), f.z);",
1232                       gradFuncName.c_str(), permFuncName.c_str());
1233     noiseCode.append("return result;");
1234     fsBuilder->emitFunction(kFloat_GrSLType, "noise", SK_ARRAY_COUNT(noiseArgs), noiseArgs,
1235                             noiseCode.c_str(), &noiseFuncName);
1236 
1237     // noiseOctaves function
1238     static const GrShaderVar noiseOctavesArgs[] =  {
1239         GrShaderVar("p", kVec3f_GrSLType),
1240         GrShaderVar("octaves", kFloat_GrSLType),
1241     };
1242     SkString noiseOctavesFuncName;
1243     SkString noiseOctavesCode;
1244     noiseOctavesCode.append("float result = 0.0;");
1245     noiseOctavesCode.append("float ratio = 1.0;");
1246     noiseOctavesCode.append("for (float i = 0.0; i < octaves; i++) {");
1247     noiseOctavesCode.appendf("result += %s(p) / ratio;", noiseFuncName.c_str());
1248     noiseOctavesCode.append("p *= 2.0;");
1249     noiseOctavesCode.append("ratio *= 2.0;");
1250     noiseOctavesCode.append("}");
1251     noiseOctavesCode.append("return (result + 1.0) / 2.0;");
1252     fsBuilder->emitFunction(kFloat_GrSLType, "noiseOctaves", SK_ARRAY_COUNT(noiseOctavesArgs),
1253                             noiseOctavesArgs, noiseOctavesCode.c_str(), &noiseOctavesFuncName);
1254 
1255     fsBuilder->codeAppendf("vec2 coords = %s * %s;", vCoords.c_str(), baseFrequencyUni);
1256     fsBuilder->codeAppendf("float r = %s(vec3(coords, %s), %s);", noiseOctavesFuncName.c_str(),
1257                            zUni, octavesUni);
1258     fsBuilder->codeAppendf("float g = %s(vec3(coords, %s + 0000.0), %s);",
1259                            noiseOctavesFuncName.c_str(), zUni, octavesUni);
1260     fsBuilder->codeAppendf("float b = %s(vec3(coords, %s + 0000.0), %s);",
1261                            noiseOctavesFuncName.c_str(), zUni, octavesUni);
1262     fsBuilder->codeAppendf("float a = %s(vec3(coords, %s + 0000.0), %s);",
1263                            noiseOctavesFuncName.c_str(), zUni, octavesUni);
1264     fsBuilder->codeAppendf("%s = vec4(r, g, b, a);", args.fOutputColor);
1265 
1266     // Clamp values
1267     fsBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
1268 
1269     // Pre-multiply the result
1270     fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
1271                            args.fOutputColor, args.fOutputColor,
1272                            args.fOutputColor, args.fOutputColor);
1273 }
1274 
GenKey(const GrProcessor & processor,const GrShaderCaps &,GrProcessorKeyBuilder * b)1275 void GrGLImprovedPerlinNoise::GenKey(const GrProcessor& processor, const GrShaderCaps&,
1276                                      GrProcessorKeyBuilder* b) {
1277 }
1278 
onSetData(const GrGLSLProgramDataManager & pdman,const GrProcessor & processor)1279 void GrGLImprovedPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman,
1280                                 const GrProcessor& processor) {
1281     INHERITED::onSetData(pdman, processor);
1282 
1283     const GrImprovedPerlinNoiseEffect& noise = processor.cast<GrImprovedPerlinNoiseEffect>();
1284 
1285     const SkVector& baseFrequency = noise.baseFrequency();
1286     pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1287 
1288     pdman.set1f(fOctavesUni, SkIntToScalar(noise.octaves()));
1289 
1290     pdman.set1f(fZUni, noise.z());
1291 }
1292 
1293 /////////////////////////////////////////////////////////////////////
asFragmentProcessor(const AsFPArgs & args) const1294 sk_sp<GrFragmentProcessor> SkPerlinNoiseShader2::asFragmentProcessor(const AsFPArgs& args) const {
1295     SkASSERT(args.fContext);
1296 
1297     SkMatrix localMatrix = this->getLocalMatrix();
1298     if (args.fLocalMatrix) {
1299         localMatrix.preConcat(*args.fLocalMatrix);
1300     }
1301 
1302     SkMatrix matrix = *args.fViewMatrix;
1303     matrix.preConcat(localMatrix);
1304 
1305     // Either we don't stitch tiles, either we have a valid tile size
1306     SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
1307 
1308     SkPerlinNoiseShader2::PaintingData* paintingData =
1309             new PaintingData(fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY, matrix);
1310 
1311     SkMatrix m = *args.fViewMatrix;
1312     m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1);
1313     m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1);
1314 
1315     if (fType == kImprovedNoise_Type) {
1316         GrSamplerParams textureParams(SkShader::TileMode::kRepeat_TileMode,
1317                                       GrSamplerParams::FilterMode::kNone_FilterMode);
1318         sk_sp<GrTextureProxy> permutationsTexture(
1319             GrRefCachedBitmapTextureProxy(args.fContext,
1320                                           paintingData->getImprovedPermutationsBitmap(),
1321                                           textureParams, nullptr));
1322         sk_sp<GrTextureProxy> gradientTexture(
1323             GrRefCachedBitmapTextureProxy(args.fContext,
1324                                           paintingData->getGradientBitmap(),
1325                                           textureParams, nullptr));
1326         return GrImprovedPerlinNoiseEffect::Make(args.fContext->resourceProvider(),
1327                                                  fNumOctaves, fSeed, paintingData,
1328                                                  std::move(permutationsTexture),
1329                                                  std::move(gradientTexture), m);
1330     }
1331 
1332     if (0 == fNumOctaves) {
1333         if (kFractalNoise_Type == fType) {
1334             // Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2)
1335             // TODO: Either treat the output of this shader as sRGB or allow client to specify a
1336             // color space of the noise. Either way, this case (and the GLSL) need to convert to
1337             // the destination.
1338             sk_sp<GrFragmentProcessor> inner(
1339                 GrConstColorProcessor::Make(GrColor4f::FromGrColor(0x80404040),
1340                                             GrConstColorProcessor::kModulateRGBA_InputMode));
1341             return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
1342         }
1343         // Emit zero.
1344         return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
1345                                            GrConstColorProcessor::kIgnore_InputMode);
1346     }
1347 
1348     sk_sp<GrTextureProxy> permutationsProxy = GrMakeCachedBitmapProxy(
1349                                                          args.fContext->resourceProvider(),
1350                                                          paintingData->getPermutationsBitmap());
1351     sk_sp<GrTextureProxy> noiseProxy = GrMakeCachedBitmapProxy(args.fContext->resourceProvider(),
1352                                                                paintingData->getNoiseBitmap());
1353 
1354     if (permutationsProxy && noiseProxy) {
1355         sk_sp<GrFragmentProcessor> inner(
1356             GrPerlinNoise2Effect::Make(args.fContext->resourceProvider(),
1357                                        fType,
1358                                        fNumOctaves,
1359                                        fStitchTiles,
1360                                        paintingData,
1361                                        std::move(permutationsProxy),
1362                                        std::move(noiseProxy),
1363                                        m));
1364         return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
1365     }
1366     delete paintingData;
1367     return nullptr;
1368 }
1369 
1370 #endif
1371 
1372 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const1373 void SkPerlinNoiseShader2::toString(SkString* str) const {
1374     str->append("SkPerlinNoiseShader2: (");
1375 
1376     str->append("type: ");
1377     switch (fType) {
1378         case kFractalNoise_Type:
1379             str->append("\"fractal noise\"");
1380             break;
1381         case kTurbulence_Type:
1382             str->append("\"turbulence\"");
1383             break;
1384         default:
1385             str->append("\"unknown\"");
1386             break;
1387     }
1388     str->append(" base frequency: (");
1389     str->appendScalar(fBaseFrequencyX);
1390     str->append(", ");
1391     str->appendScalar(fBaseFrequencyY);
1392     str->append(") number of octaves: ");
1393     str->appendS32(fNumOctaves);
1394     str->append(" seed: ");
1395     str->appendScalar(fSeed);
1396     str->append(" stitch tiles: ");
1397     str->append(fStitchTiles ? "true " : "false ");
1398 
1399     this->INHERITED::toString(str);
1400 
1401     str->append(")");
1402 }
1403 #endif
1404