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