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