1e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com/* 2e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * Copyright 2013 Google Inc. 3e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * 4e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * Use of this source code is governed by a BSD-style license that can be 5e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com * found in the LICENSE file. 6e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com */ 7e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 8e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#include "SkDither.h" 9e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#include "SkPerlinNoiseShader.h" 10c2a0ea6418988d4bcc0719f99b1a110cecd08679commit-bot@chromium.org#include "SkColorFilter.h" 118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h" 128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 13e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#include "SkShader.h" 14e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#include "SkUnPreMultiply.h" 15e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#include "SkString.h" 16e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 17e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#if SK_SUPPORT_GPU 18e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#include "GrContext.h" 1977af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com#include "GrCoordTransform.h" 20b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "gl/GrGLProcessor.h" 2130ba436f04e61d4505fb854d5fc56079636e0788joshualitt#include "gl/builders/GrGLProgramBuilder.h" 22b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrTBackendProcessorFactory.h" 23e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#include "SkGr.h" 24e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#endif 25e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 26e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comstatic const int kBlockSize = 256; 27e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comstatic const int kBlockMask = kBlockSize - 1; 28e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comstatic const int kPerlinNoise = 4096; 29e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comstatic const int kRandMaximum = SK_MaxS32; // 2**31 - 1 30e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 31e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comnamespace { 32e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 33e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com// noiseValue is the color component's value (or color) 34e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com// limitValue is the maximum perlin noise array index value allowed 35e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com// newValue is the current noise dimension (either width or height) 36e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.cominline int checkNoise(int noiseValue, int limitValue, int newValue) { 37e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // If the noise value would bring us out of bounds of the current noise array while we are 38e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // stiching noise tiles together, wrap the noise around the current dimension of the noise to 39e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // stay within the array bounds in a continuous fashion (so that tiling lines are not visible) 40e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com if (noiseValue >= limitValue) { 41e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com noiseValue -= newValue; 42e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 43e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com return noiseValue; 44e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 45e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 46e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.cominline SkScalar smoothCurve(SkScalar t) { 474b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org static const SkScalar SK_Scalar3 = 3.0f; 48e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 49e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // returns t * t * (3 - 2 * t) 50e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com return SkScalarMul(SkScalarSquare(t), SK_Scalar3 - 2 * t); 51e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 52e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 53ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.orgbool perlin_noise_type_is_valid(SkPerlinNoiseShader::Type type) { 54ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org return (SkPerlinNoiseShader::kFractalNoise_Type == type) || 55ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org (SkPerlinNoiseShader::kTurbulence_Type == type); 56ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org} 57ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org 58e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} // end namespace 59e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 60e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comstruct SkPerlinNoiseShader::StitchData { 61e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com StitchData() 62e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com : fWidth(0) 63e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com , fWrapX(0) 64e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com , fHeight(0) 65e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com , fWrapY(0) 66e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com {} 67e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 68e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com bool operator==(const StitchData& other) const { 69e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com return fWidth == other.fWidth && 70e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fWrapX == other.fWrapX && 71e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fHeight == other.fHeight && 72e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fWrapY == other.fWrapY; 73e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 74e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 75e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int fWidth; // How much to subtract to wrap for stitching. 76e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int fWrapX; // Minimum value to wrap. 77e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int fHeight; 78e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int fWrapY; 79e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}; 80e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 81e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comstruct SkPerlinNoiseShader::PaintingData { 82fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org PaintingData(const SkISize& tileSize, SkScalar seed, 83ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkScalar baseFrequencyX, SkScalar baseFrequencyY, 84ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco const SkMatrix& matrix) 85e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com { 86ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkVector wavelength = SkVector::Make(SkScalarInvert(baseFrequencyX), 87ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkScalarInvert(baseFrequencyY)); 88ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco matrix.mapVectors(&wavelength, 1); 89ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco fBaseFrequency.fX = SkScalarInvert(wavelength.fX); 90ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco fBaseFrequency.fY = SkScalarInvert(wavelength.fY); 91ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkVector sizeVec = SkVector::Make(SkIntToScalar(tileSize.fWidth), 92ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkIntToScalar(tileSize.fHeight)); 93ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco matrix.mapVectors(&sizeVec, 1); 94ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco fTileSize.fWidth = SkScalarRoundToInt(sizeVec.fX); 95ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco fTileSize.fHeight = SkScalarRoundToInt(sizeVec.fY); 96fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org this->init(seed); 97fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org if (!fTileSize.isEmpty()) { 98fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org this->stitch(); 99fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org } 100fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org 101f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco#if SK_SUPPORT_GPU 102a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org fPermutationsBitmap.setInfo(SkImageInfo::MakeA8(kBlockSize, 1)); 103fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org fPermutationsBitmap.setPixels(fLatticeSelector); 104fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org 105a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org fNoiseBitmap.setInfo(SkImageInfo::MakeN32Premul(kBlockSize, 4)); 106fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org fNoiseBitmap.setPixels(fNoise[0][0]); 107fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org#endif 108e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 109e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 110e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int fSeed; 111e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com uint8_t fLatticeSelector[kBlockSize]; 112e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com uint16_t fNoise[4][kBlockSize][2]; 113e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkPoint fGradient[4][kBlockSize]; 114e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkISize fTileSize; 115e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkVector fBaseFrequency; 116e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com StitchData fStitchDataInit; 117e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 118e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comprivate: 119e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 120f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco#if SK_SUPPORT_GPU 121fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org SkBitmap fPermutationsBitmap; 122fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org SkBitmap fNoiseBitmap; 123fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org#endif 124e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 125e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com inline int random() { 126e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com static const int gRandAmplitude = 16807; // 7**5; primitive root of m 127e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com static const int gRandQ = 127773; // m / a 128e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com static const int gRandR = 2836; // m % a 129e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 130e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int result = gRandAmplitude * (fSeed % gRandQ) - gRandR * (fSeed / gRandQ); 131e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com if (result <= 0) 132e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com result += kRandMaximum; 133e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fSeed = result; 134e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com return result; 135e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 136e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 137fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org // Only called once. Could be part of the constructor. 138e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com void init(SkScalar seed) 139e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com { 140e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com static const SkScalar gInvBlockSizef = SkScalarInvert(SkIntToScalar(kBlockSize)); 141e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 142857e320300372dab938c0dbffadc3c2c8a893b92senorblanco@chromium.org // According to the SVG spec, we must truncate (not round) the seed value. 143857e320300372dab938c0dbffadc3c2c8a893b92senorblanco@chromium.org fSeed = SkScalarTruncToInt(seed); 144e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // The seed value clamp to the range [1, kRandMaximum - 1]. 145e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com if (fSeed <= 0) { 146e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fSeed = -(fSeed % (kRandMaximum - 1)) + 1; 147e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 148e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com if (fSeed > kRandMaximum - 1) { 149e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fSeed = kRandMaximum - 1; 150e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 151e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int channel = 0; channel < 4; ++channel) { 152e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int i = 0; i < kBlockSize; ++i) { 153e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fLatticeSelector[i] = i; 154e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fNoise[channel][i][0] = (random() % (2 * kBlockSize)); 155e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fNoise[channel][i][1] = (random() % (2 * kBlockSize)); 156e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 157e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 158e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int i = kBlockSize - 1; i > 0; --i) { 159e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int k = fLatticeSelector[i]; 160e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int j = random() % kBlockSize; 161e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkASSERT(j >= 0); 162e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkASSERT(j < kBlockSize); 163e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fLatticeSelector[i] = fLatticeSelector[j]; 164e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fLatticeSelector[j] = k; 165e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 166e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 167e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Perform the permutations now 168e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com { 169e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Copy noise data 170e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com uint16_t noise[4][kBlockSize][2]; 171e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int i = 0; i < kBlockSize; ++i) { 172e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int channel = 0; channel < 4; ++channel) { 173e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int j = 0; j < 2; ++j) { 174e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com noise[channel][i][j] = fNoise[channel][i][j]; 175e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 176e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 177e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 178e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Do permutations on noise data 179e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int i = 0; i < kBlockSize; ++i) { 180e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int channel = 0; channel < 4; ++channel) { 181e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int j = 0; j < 2; ++j) { 182e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fNoise[channel][i][j] = noise[channel][fLatticeSelector[i]][j]; 183e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 184e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 185e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 186e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 187e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 188e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Half of the largest possible value for 16 bit unsigned int 1894b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org static const SkScalar gHalfMax16bits = 32767.5f; 190e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 191e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Compute gradients from permutated noise data 192e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int channel = 0; channel < 4; ++channel) { 193e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int i = 0; i < kBlockSize; ++i) { 194e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fGradient[channel][i] = SkPoint::Make( 195e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalarMul(SkIntToScalar(fNoise[channel][i][0] - kBlockSize), 196e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com gInvBlockSizef), 197cff0243b0ff1de25b3d99e2bf15a30c0e0a31261skia.committer@gmail.com SkScalarMul(SkIntToScalar(fNoise[channel][i][1] - kBlockSize), 198e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com gInvBlockSizef)); 199e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fGradient[channel][i].normalize(); 200e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Put the normalized gradient back into the noise data 201e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fNoise[channel][i][0] = SkScalarRoundToInt(SkScalarMul( 202d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com fGradient[channel][i].fX + SK_Scalar1, gHalfMax16bits)); 203e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fNoise[channel][i][1] = SkScalarRoundToInt(SkScalarMul( 204d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com fGradient[channel][i].fY + SK_Scalar1, gHalfMax16bits)); 205e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 206e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 207e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 208e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 209fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org // Only called once. Could be part of the constructor. 210e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com void stitch() { 211e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar tileWidth = SkIntToScalar(fTileSize.width()); 212e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar tileHeight = SkIntToScalar(fTileSize.height()); 213e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkASSERT(tileWidth > 0 && tileHeight > 0); 214e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // When stitching tiled turbulence, the frequencies must be adjusted 215e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // so that the tile borders will be continuous. 216e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com if (fBaseFrequency.fX) { 2178015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com SkScalar lowFrequencx = 2188015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com SkScalarFloorToScalar(tileWidth * fBaseFrequency.fX) / tileWidth; 2198015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com SkScalar highFrequencx = 2208015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com SkScalarCeilToScalar(tileWidth * fBaseFrequency.fX) / tileWidth; 221e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // BaseFrequency should be non-negative according to the standard. 222cff0243b0ff1de25b3d99e2bf15a30c0e0a31261skia.committer@gmail.com if (SkScalarDiv(fBaseFrequency.fX, lowFrequencx) < 223e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalarDiv(highFrequencx, fBaseFrequency.fX)) { 224e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fBaseFrequency.fX = lowFrequencx; 225e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } else { 226e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fBaseFrequency.fX = highFrequencx; 227e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 228e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 229e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com if (fBaseFrequency.fY) { 2308015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com SkScalar lowFrequency = 2318015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com SkScalarFloorToScalar(tileHeight * fBaseFrequency.fY) / tileHeight; 2328015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com SkScalar highFrequency = 2338015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com SkScalarCeilToScalar(tileHeight * fBaseFrequency.fY) / tileHeight; 234cff0243b0ff1de25b3d99e2bf15a30c0e0a31261skia.committer@gmail.com if (SkScalarDiv(fBaseFrequency.fY, lowFrequency) < 235e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalarDiv(highFrequency, fBaseFrequency.fY)) { 236e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fBaseFrequency.fY = lowFrequency; 237e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } else { 238e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fBaseFrequency.fY = highFrequency; 239e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 240e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 241e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Set up TurbulenceInitial stitch values. 242e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fStitchDataInit.fWidth = 2438015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com SkScalarRoundToInt(tileWidth * fBaseFrequency.fX); 244e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fStitchDataInit.fWrapX = kPerlinNoise + fStitchDataInit.fWidth; 245e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fStitchDataInit.fHeight = 2468015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com SkScalarRoundToInt(tileHeight * fBaseFrequency.fY); 247e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fStitchDataInit.fWrapY = kPerlinNoise + fStitchDataInit.fHeight; 248e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 249e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 250fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.orgpublic: 251e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 252f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco#if SK_SUPPORT_GPU 253fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org const SkBitmap& getPermutationsBitmap() const { return fPermutationsBitmap; } 254fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org 255fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org const SkBitmap& getNoiseBitmap() const { return fNoiseBitmap; } 256fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org#endif 257e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}; 258e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 259e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comSkShader* SkPerlinNoiseShader::CreateFractalNoise(SkScalar baseFrequencyX, SkScalar baseFrequencyY, 260e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int numOctaves, SkScalar seed, 261e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const SkISize* tileSize) { 262e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com return SkNEW_ARGS(SkPerlinNoiseShader, (kFractalNoise_Type, baseFrequencyX, baseFrequencyY, 263e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com numOctaves, seed, tileSize)); 264e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 265e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 2669fbbcca1c958e6df2cff24d3ccdb7ebd89b8486bcommit-bot@chromium.orgSkShader* SkPerlinNoiseShader::CreateTurbulence(SkScalar baseFrequencyX, SkScalar baseFrequencyY, 267e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int numOctaves, SkScalar seed, 268e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const SkISize* tileSize) { 269e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com return SkNEW_ARGS(SkPerlinNoiseShader, (kTurbulence_Type, baseFrequencyX, baseFrequencyY, 270e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com numOctaves, seed, tileSize)); 271e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 272e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 273e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comSkPerlinNoiseShader::SkPerlinNoiseShader(SkPerlinNoiseShader::Type type, 274e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar baseFrequencyX, 275e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar baseFrequencyY, 276e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int numOctaves, 277e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar seed, 278e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const SkISize* tileSize) 279e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com : fType(type) 280e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com , fBaseFrequencyX(baseFrequencyX) 281e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com , fBaseFrequencyY(baseFrequencyY) 282ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org , fNumOctaves(numOctaves > 255 ? 255 : numOctaves/*[0,255] octaves allowed*/) 283e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com , fSeed(seed) 284fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org , fTileSize(NULL == tileSize ? SkISize::Make(0, 0) : *tileSize) 285fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org , fStitchTiles(!fTileSize.isEmpty()) 286e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com{ 287e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkASSERT(numOctaves >= 0 && numOctaves < 256); 288e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 289e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 2909fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING 2919fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkPerlinNoiseShader::SkPerlinNoiseShader(SkReadBuffer& buffer) : INHERITED(buffer) { 292e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fType = (SkPerlinNoiseShader::Type) buffer.readInt(); 293e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fBaseFrequencyX = buffer.readScalar(); 294e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fBaseFrequencyY = buffer.readScalar(); 295e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fNumOctaves = buffer.readInt(); 296e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fSeed = buffer.readScalar(); 297e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fStitchTiles = buffer.readBool(); 298e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fTileSize.fWidth = buffer.readInt(); 299e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fTileSize.fHeight = buffer.readInt(); 300ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org buffer.validate(perlin_noise_type_is_valid(fType) && 301fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org (fNumOctaves >= 0) && (fNumOctaves <= 255) && 302fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org (fStitchTiles != fTileSize.isEmpty())); 303e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 3049fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif 305e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 306e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comSkPerlinNoiseShader::~SkPerlinNoiseShader() { 307e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 308e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 3099fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkPerlinNoiseShader::CreateProc(SkReadBuffer& buffer) { 3109fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed Type type = (Type)buffer.readInt(); 3119fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkScalar freqX = buffer.readScalar(); 3129fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkScalar freqY = buffer.readScalar(); 3139fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed int octaves = buffer.readInt(); 3149fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkScalar seed = buffer.readScalar(); 3159fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkISize tileSize; 3169fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed tileSize.fWidth = buffer.readInt(); 3179fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed tileSize.fHeight = buffer.readInt(); 3189fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 3199fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed switch (type) { 3209fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed case kFractalNoise_Type: 3219fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed return SkPerlinNoiseShader::CreateFractalNoise(freqX, freqY, octaves, seed, &tileSize); 3229fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed case kTurbulence_Type: 3239fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed return SkPerlinNoiseShader::CreateTubulence(freqX, freqY, octaves, seed, &tileSize); 3249fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed default: 3259fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed return NULL; 3269fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 3279fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 3289fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 3298b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkPerlinNoiseShader::flatten(SkWriteBuffer& buffer) const { 330e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com buffer.writeInt((int) fType); 331e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com buffer.writeScalar(fBaseFrequencyX); 332e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com buffer.writeScalar(fBaseFrequencyY); 333e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com buffer.writeInt(fNumOctaves); 334e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com buffer.writeScalar(fSeed); 335e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com buffer.writeInt(fTileSize.fWidth); 336e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com buffer.writeInt(fTileSize.fHeight); 337e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 338e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 33987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::noise2D( 340ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco int channel, const StitchData& stitchData, const SkPoint& noiseVector) const { 341e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com struct Noise { 342e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int noisePositionIntegerValue; 343ce6a354e121915c2925e545e7df2929492d69d50senorblanco int nextNoisePositionIntegerValue; 344e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar noisePositionFractionValue; 345e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com Noise(SkScalar component) 346e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com { 347e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar position = component + kPerlinNoise; 348e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com noisePositionIntegerValue = SkScalarFloorToInt(position); 349e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com noisePositionFractionValue = position - SkIntToScalar(noisePositionIntegerValue); 350ce6a354e121915c2925e545e7df2929492d69d50senorblanco nextNoisePositionIntegerValue = noisePositionIntegerValue + 1; 351e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 352e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com }; 353e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com Noise noiseX(noiseVector.x()); 354e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com Noise noiseY(noiseVector.y()); 355e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar u, v; 35687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader); 357e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // If stitching, adjust lattice points accordingly. 35887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (perlinNoiseShader.fStitchTiles) { 359e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com noiseX.noisePositionIntegerValue = 360e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth); 361e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com noiseY.noisePositionIntegerValue = 362e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight); 363ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseX.nextNoisePositionIntegerValue = 364ce6a354e121915c2925e545e7df2929492d69d50senorblanco checkNoise(noiseX.nextNoisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth); 365ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseY.nextNoisePositionIntegerValue = 366ce6a354e121915c2925e545e7df2929492d69d50senorblanco checkNoise(noiseY.nextNoisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight); 367e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 368e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com noiseX.noisePositionIntegerValue &= kBlockMask; 369e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com noiseY.noisePositionIntegerValue &= kBlockMask; 370ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseX.nextNoisePositionIntegerValue &= kBlockMask; 371ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseY.nextNoisePositionIntegerValue &= kBlockMask; 372ce6a354e121915c2925e545e7df2929492d69d50senorblanco int i = 373ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco fPaintingData->fLatticeSelector[noiseX.noisePositionIntegerValue]; 374ce6a354e121915c2925e545e7df2929492d69d50senorblanco int j = 375ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco fPaintingData->fLatticeSelector[noiseX.nextNoisePositionIntegerValue]; 376ce6a354e121915c2925e545e7df2929492d69d50senorblanco int b00 = (i + noiseY.noisePositionIntegerValue) & kBlockMask; 377ce6a354e121915c2925e545e7df2929492d69d50senorblanco int b10 = (j + noiseY.noisePositionIntegerValue) & kBlockMask; 378ce6a354e121915c2925e545e7df2929492d69d50senorblanco int b01 = (i + noiseY.nextNoisePositionIntegerValue) & kBlockMask; 379ce6a354e121915c2925e545e7df2929492d69d50senorblanco int b11 = (j + noiseY.nextNoisePositionIntegerValue) & kBlockMask; 380e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar sx = smoothCurve(noiseX.noisePositionFractionValue); 381e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar sy = smoothCurve(noiseY.noisePositionFractionValue); 382e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement 383e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkPoint fractionValue = SkPoint::Make(noiseX.noisePositionFractionValue, 384e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com noiseY.noisePositionFractionValue); // Offset (0,0) 385ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco u = fPaintingData->fGradient[channel][b00].dot(fractionValue); 386e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fractionValue.fX -= SK_Scalar1; // Offset (-1,0) 387ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco v = fPaintingData->fGradient[channel][b10].dot(fractionValue); 388e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar a = SkScalarInterp(u, v, sx); 389e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fractionValue.fY -= SK_Scalar1; // Offset (-1,-1) 390ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco v = fPaintingData->fGradient[channel][b11].dot(fractionValue); 391e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1) 392ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco u = fPaintingData->fGradient[channel][b01].dot(fractionValue); 393e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar b = SkScalarInterp(u, v, sx); 394e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com return SkScalarInterp(a, b, sy); 395e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 396e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 39787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::calculateTurbulenceValueForPoint( 398ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco int channel, StitchData& stitchData, const SkPoint& point) const { 39987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader); 40087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (perlinNoiseShader.fStitchTiles) { 401e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Set up TurbulenceInitial stitch values. 402ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco stitchData = fPaintingData->fStitchDataInit; 403e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 404e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar turbulenceFunctionResult = 0; 405ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkPoint noiseVector(SkPoint::Make(SkScalarMul(point.x(), fPaintingData->fBaseFrequency.fX), 406ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkScalarMul(point.y(), fPaintingData->fBaseFrequency.fY))); 407e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar ratio = SK_Scalar1; 40887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) { 409ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkScalar noise = noise2D(channel, stitchData, noiseVector); 410e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com turbulenceFunctionResult += SkScalarDiv( 41187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org (perlinNoiseShader.fType == kFractalNoise_Type) ? noise : SkScalarAbs(noise), ratio); 412e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com noiseVector.fX *= 2; 413e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com noiseVector.fY *= 2; 414e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com ratio *= 2; 41587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (perlinNoiseShader.fStitchTiles) { 416e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Update stitch values 417e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com stitchData.fWidth *= 2; 418e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com stitchData.fWrapX = stitchData.fWidth + kPerlinNoise; 419e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com stitchData.fHeight *= 2; 420e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com stitchData.fWrapY = stitchData.fHeight + kPerlinNoise; 421e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 422e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 423e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 424e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2 425e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // by fractalNoise and (turbulenceFunctionResult) by turbulence. 42687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (perlinNoiseShader.fType == kFractalNoise_Type) { 427e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com turbulenceFunctionResult = 428e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalarMul(turbulenceFunctionResult, SK_ScalarHalf) + SK_ScalarHalf; 429e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 430e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 431e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com if (channel == 3) { // Scale alpha by paint value 432e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com turbulenceFunctionResult = SkScalarMul(turbulenceFunctionResult, 433e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalarDiv(SkIntToScalar(getPaintAlpha()), SkIntToScalar(255))); 434e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 435e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 436e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Clamp result 437e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1); 438e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 439e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 44087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkPMColor SkPerlinNoiseShader::PerlinNoiseShaderContext::shade( 44187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const SkPoint& point, StitchData& stitchData) const { 442e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkPoint newPoint; 443a8d95f899bf3fe404d3cd5c357531ff852c15b29senorblanco@chromium.org fMatrix.mapPoints(&newPoint, &point, 1); 444e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com newPoint.fX = SkScalarRoundToScalar(newPoint.fX); 445e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com newPoint.fY = SkScalarRoundToScalar(newPoint.fY); 446e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 447e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com U8CPU rgba[4]; 448e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int channel = 3; channel >= 0; --channel) { 449e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com rgba[channel] = SkScalarFloorToInt(255 * 450ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco calculateTurbulenceValueForPoint(channel, stitchData, newPoint)); 451e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 452e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]); 453e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 454e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 455ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.orgSkShader::Context* SkPerlinNoiseShader::onCreateContext(const ContextRec& rec, 456ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org void* storage) const { 457e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org return SkNEW_PLACEMENT_ARGS(storage, PerlinNoiseShaderContext, (*this, rec)); 45887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org} 45987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 46087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgsize_t SkPerlinNoiseShader::contextSize() const { 46187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org return sizeof(PerlinNoiseShaderContext); 46287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org} 46387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 46487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkPerlinNoiseShader::PerlinNoiseShaderContext::PerlinNoiseShaderContext( 465e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org const SkPerlinNoiseShader& shader, const ContextRec& rec) 466e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org : INHERITED(shader, rec) 46787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org{ 468e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org SkMatrix newMatrix = *rec.fMatrix; 469b67b8e6052bf5567eb3f9726dda99a6b260dfb05reed@google.com newMatrix.preConcat(shader.getLocalMatrix()); 470b67b8e6052bf5567eb3f9726dda99a6b260dfb05reed@google.com if (rec.fLocalMatrix) { 471b67b8e6052bf5567eb3f9726dda99a6b260dfb05reed@google.com newMatrix.preConcat(*rec.fLocalMatrix); 472b67b8e6052bf5567eb3f9726dda99a6b260dfb05reed@google.com } 473a8d95f899bf3fe404d3cd5c357531ff852c15b29senorblanco@chromium.org // This (1,1) translation is due to WebKit's 1 based coordinates for the noise 474a8d95f899bf3fe404d3cd5c357531ff852c15b29senorblanco@chromium.org // (as opposed to 0 based, usually). The same adjustment is in the setData() function. 475ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco fMatrix.setTranslate(-newMatrix.getTranslateX() + SK_Scalar1, -newMatrix.getTranslateY() + SK_Scalar1); 476ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco fPaintingData = SkNEW_ARGS(PaintingData, (shader.fTileSize, shader.fSeed, shader.fBaseFrequencyX, shader.fBaseFrequencyY, newMatrix)); 477ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco} 478ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco 479ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblancoSkPerlinNoiseShader::PerlinNoiseShaderContext::~PerlinNoiseShaderContext() { 480ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkDELETE(fPaintingData); 481e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 482e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 48387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgvoid SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan( 48487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org int x, int y, SkPMColor result[], int count) { 485e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y)); 486e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com StitchData stitchData; 487e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int i = 0; i < count; ++i) { 488e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com result[i] = shade(point, stitchData); 489e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com point.fX += SK_Scalar1; 490e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 491e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 492e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 49387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgvoid SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan16( 49487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org int x, int y, uint16_t result[], int count) { 495e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y)); 496e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com StitchData stitchData; 497e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com DITHER_565_SCAN(y); 498e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int i = 0; i < count; ++i) { 499e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com unsigned dither = DITHER_VALUE(x); 500e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com result[i] = SkDitherRGB32To565(shade(point, stitchData), dither); 501e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com DITHER_INC_X(x); 502e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com point.fX += SK_Scalar1; 503e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 504e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 505e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 506e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com///////////////////////////////////////////////////////////////////// 507e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 508344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org#if SK_SUPPORT_GPU 509e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 510b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrTBackendProcessorFactory.h" 511e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 512b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GrGLPerlinNoise : public GrGLFragmentProcessor { 5134775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.compublic: 514b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrGLPerlinNoise(const GrBackendProcessorFactory&, 515b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessor&); 5164775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com virtual ~GrGLPerlinNoise() {} 517e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 51830ba436f04e61d4505fb854d5fc56079636e0788joshualitt virtual void emitCode(GrGLProgramBuilder*, 519b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrFragmentProcessor&, 520b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessorKey&, 521e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* outputColor, 522e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* inputColor, 52377af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com const TransformedCoordsArray&, 524e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const TextureSamplerArray&) SK_OVERRIDE; 525e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 526b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE; 5274775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com 528b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder* b); 5294775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com 530f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblancoprivate: 531e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 5327510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen GrGLProgramDataManager::UniformHandle fStitchDataUni; 5337510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen SkPerlinNoiseShader::Type fType; 5347510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen bool fStitchTiles; 5357510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen int fNumOctaves; 5367510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen GrGLProgramDataManager::UniformHandle fBaseFrequencyUni; 5377510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen GrGLProgramDataManager::UniformHandle fAlphaUni; 538e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 539e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comprivate: 540b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt typedef GrGLFragmentProcessor INHERITED; 541e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}; 542e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 543e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com///////////////////////////////////////////////////////////////////// 544e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 545b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GrPerlinNoiseEffect : public GrFragmentProcessor { 546e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.compublic: 547b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt static GrFragmentProcessor* Create(SkPerlinNoiseShader::Type type, 548b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt int numOctaves, bool stitchTiles, 549b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkPerlinNoiseShader::PaintingData* paintingData, 550b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrTexture* permutationsTexture, GrTexture* noiseTexture, 551b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const SkMatrix& matrix, uint8_t alpha) { 55255fad7af61c21d502acb9891d631e8aa29e3628cbsalomon return SkNEW_ARGS(GrPerlinNoiseEffect, (type, numOctaves, stitchTiles, paintingData, 55355fad7af61c21d502acb9891d631e8aa29e3628cbsalomon permutationsTexture, noiseTexture, matrix, alpha)); 554e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 555e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 556ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco virtual ~GrPerlinNoiseEffect() { 557ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkDELETE(fPaintingData); 558ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco } 559e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 560e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com static const char* Name() { return "PerlinNoise"; } 561b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE { 562b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt return GrTBackendFragmentProcessorFactory<GrPerlinNoiseEffect>::getInstance(); 563e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 564ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco const SkPerlinNoiseShader::StitchData& stitchData() const { return fPaintingData->fStitchDataInit; } 565e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 566f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco SkPerlinNoiseShader::Type type() const { return fType; } 567f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco bool stitchTiles() const { return fStitchTiles; } 568ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; } 569f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco int numOctaves() const { return fNumOctaves; } 570f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); } 571f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco uint8_t alpha() const { return fAlpha; } 572f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco 573b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt typedef GrGLPerlinNoise GLProcessor; 574e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 575e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comprivate: 576b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt virtual bool onIsEqual(const GrProcessor& sBase) const SK_OVERRIDE { 57749586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt const GrPerlinNoiseEffect& s = sBase.cast<GrPerlinNoiseEffect>(); 578f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco return fType == s.fType && 579ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency && 580f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco fNumOctaves == s.fNumOctaves && 581f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco fStitchTiles == s.fStitchTiles && 582f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco fCoordTransform.getMatrix() == s.fCoordTransform.getMatrix() && 583f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco fAlpha == s.fAlpha && 5844775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com fPermutationsAccess.getTexture() == s.fPermutationsAccess.getTexture() && 585e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fNoiseAccess.getTexture() == s.fNoiseAccess.getTexture() && 586ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco fPaintingData->fStitchDataInit == s.fPaintingData->fStitchDataInit; 587e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 588e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 589ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco GrPerlinNoiseEffect(SkPerlinNoiseShader::Type type, 590e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int numOctaves, bool stitchTiles, 591ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkPerlinNoiseShader::PaintingData* paintingData, 592e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com GrTexture* permutationsTexture, GrTexture* noiseTexture, 593e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const SkMatrix& matrix, uint8_t alpha) 594f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco : fType(type) 595f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco , fNumOctaves(numOctaves) 596f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco , fStitchTiles(stitchTiles) 597f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco , fAlpha(alpha) 5984775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com , fPermutationsAccess(permutationsTexture) 599e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com , fNoiseAccess(noiseTexture) 600ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco , fPaintingData(paintingData) { 601e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com this->addTextureAccess(&fPermutationsAccess); 602e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com this->addTextureAccess(&fNoiseAccess); 603ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco fCoordTransform.reset(kLocal_GrCoordSet, matrix); 604f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco this->addCoordTransform(&fCoordTransform); 605f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco this->setWillNotUseInputColor(); 606e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 607e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 608b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 609e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 610f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco SkPerlinNoiseShader::Type fType; 611f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco GrCoordTransform fCoordTransform; 612f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco int fNumOctaves; 613f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco bool fStitchTiles; 614f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco uint8_t fAlpha; 615e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com GrTextureAccess fPermutationsAccess; 616e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com GrTextureAccess fNoiseAccess; 617ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkPerlinNoiseShader::PaintingData *fPaintingData; 618e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 619f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco void getConstantColorComponents(GrColor*, uint32_t* validFlags) const SK_OVERRIDE { 620f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco *validFlags = 0; // This is noise. Nothing is constant. 6214775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com } 6224775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com 6234775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.comprivate: 624b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt typedef GrFragmentProcessor INHERITED; 625e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}; 626e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 627e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com///////////////////////////////////////////////////////////////////// 628b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrPerlinNoiseEffect); 629e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 630b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrFragmentProcessor* GrPerlinNoiseEffect::TestCreate(SkRandom* random, 631b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrContext* context, 632b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrDrawTargetCaps&, 633b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrTexture**) { 634423ac13f351b22308d3b1d039ab4859540be0b9dsugoi@google.com int numOctaves = random->nextRangeU(2, 10); 635e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com bool stitchTiles = random->nextBool(); 636e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar seed = SkIntToScalar(random->nextU()); 637e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkISize tileSize = SkISize::Make(random->nextRangeU(4, 4096), random->nextRangeU(4, 4096)); 6384b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org SkScalar baseFrequencyX = random->nextRangeScalar(0.01f, 6394b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org 0.99f); 6404b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org SkScalar baseFrequencyY = random->nextRangeScalar(0.01f, 6414b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org 0.99f); 642e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 643e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkShader* shader = random->nextBool() ? 644e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkPerlinNoiseShader::CreateFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves, seed, 645e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com stitchTiles ? &tileSize : NULL) : 6469fbbcca1c958e6df2cff24d3ccdb7ebd89b8486bcommit-bot@chromium.org SkPerlinNoiseShader::CreateTurbulence(baseFrequencyX, baseFrequencyY, numOctaves, seed, 647e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com stitchTiles ? &tileSize : NULL); 648e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 649e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkPaint paint; 65083d081ae1d731b5039e99823620f5e287542ee39bsalomon GrColor paintColor; 651b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrFragmentProcessor* effect; 652b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkAssertResult(shader->asFragmentProcessor(context, paint, NULL, &paintColor, &effect)); 653e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 654e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkDELETE(shader); 655e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 656e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com return effect; 657e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 6584775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com 659b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrGLPerlinNoise::GrGLPerlinNoise(const GrBackendProcessorFactory& factory, 660b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessor& processor) 661f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco : INHERITED (factory) 662b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt , fType(processor.cast<GrPerlinNoiseEffect>().type()) 663b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt , fStitchTiles(processor.cast<GrPerlinNoiseEffect>().stitchTiles()) 664b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt , fNumOctaves(processor.cast<GrPerlinNoiseEffect>().numOctaves()) { 6654775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com} 6664775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com 66730ba436f04e61d4505fb854d5fc56079636e0788joshualittvoid GrGLPerlinNoise::emitCode(GrGLProgramBuilder* builder, 668b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrFragmentProcessor&, 669b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessorKey& key, 670e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* outputColor, 671e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* inputColor, 67277af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com const TransformedCoordsArray& coords, 673e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const TextureSamplerArray& samplers) { 674e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com sk_ignore_unused_variable(inputColor); 675e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 67630ba436f04e61d4505fb854d5fc56079636e0788joshualitt GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); 67730ba436f04e61d4505fb854d5fc56079636e0788joshualitt SkString vCoords = fsBuilder->ensureFSCoords2D(coords, 0); 678e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 67930ba436f04e61d4505fb854d5fc56079636e0788joshualitt fBaseFrequencyUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 680e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com kVec2f_GrSLType, "baseFrequency"); 681e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* baseFrequencyUni = builder->getUniformCStr(fBaseFrequencyUni); 68230ba436f04e61d4505fb854d5fc56079636e0788joshualitt fAlphaUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 683e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com kFloat_GrSLType, "alpha"); 684e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* alphaUni = builder->getUniformCStr(fAlphaUni); 685e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 686e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* stitchDataUni = NULL; 687e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com if (fStitchTiles) { 68830ba436f04e61d4505fb854d5fc56079636e0788joshualitt fStitchDataUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 6899839320ae17ab1c2182dc144db5ba94caa1bde56commit-bot@chromium.org kVec2f_GrSLType, "stitchData"); 690e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com stitchDataUni = builder->getUniformCStr(fStitchDataUni); 691e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 692e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 693d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8 694d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com const char* chanCoordR = "0.125"; 695d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com const char* chanCoordG = "0.375"; 696d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com const char* chanCoordB = "0.625"; 697d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com const char* chanCoordA = "0.875"; 698d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com const char* chanCoord = "chanCoord"; 699e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* stitchData = "stitchData"; 700e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* ratio = "ratio"; 701e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* noiseVec = "noiseVec"; 702e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* noiseSmooth = "noiseSmooth"; 703ce6a354e121915c2925e545e7df2929492d69d50senorblanco const char* floorVal = "floorVal"; 704e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* fractVal = "fractVal"; 705e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* uv = "uv"; 706e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* ab = "ab"; 707e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* latticeIdx = "latticeIdx"; 708ce6a354e121915c2925e545e7df2929492d69d50senorblanco const char* bcoords = "bcoords"; 709e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* lattice = "lattice"; 710e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* inc8bit = "0.00390625"; // 1.0 / 256.0 711e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a 712e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // [-1,1] vector and perform a dot product between that vector and the provided vector. 713e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* dotLattice = "dot(((%s.ga + %s.rb * vec2(%s)) * vec2(2.0) - vec2(1.0)), %s);"; 714e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 715d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com // Add noise function 716d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com static const GrGLShaderVar gPerlinNoiseArgs[] = { 717d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com GrGLShaderVar(chanCoord, kFloat_GrSLType), 7189839320ae17ab1c2182dc144db5ba94caa1bde56commit-bot@chromium.org GrGLShaderVar(noiseVec, kVec2f_GrSLType) 719d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com }; 720e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 721d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com static const GrGLShaderVar gPerlinNoiseStitchArgs[] = { 722d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com GrGLShaderVar(chanCoord, kFloat_GrSLType), 7239839320ae17ab1c2182dc144db5ba94caa1bde56commit-bot@chromium.org GrGLShaderVar(noiseVec, kVec2f_GrSLType), 7249839320ae17ab1c2182dc144db5ba94caa1bde56commit-bot@chromium.org GrGLShaderVar(stitchData, kVec2f_GrSLType) 725d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com }; 726e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 727d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com SkString noiseCode; 728e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 729ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseCode.appendf("\tvec4 %s;\n", floorVal); 730ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec); 731ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal); 732ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec); 733e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 734e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // smooth curve : t * t * (3 - 2 * t) 735ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);", 736ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseSmooth, fractVal, fractVal, fractVal); 737e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 738e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Adjust frequencies if we're stitching tiles 739e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com if (fStitchTiles) { 7409839320ae17ab1c2182dc144db5ba94caa1bde56commit-bot@chromium.org noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }", 741ce6a354e121915c2925e545e7df2929492d69d50senorblanco floorVal, stitchData, floorVal, stitchData); 7429839320ae17ab1c2182dc144db5ba94caa1bde56commit-bot@chromium.org noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }", 743ce6a354e121915c2925e545e7df2929492d69d50senorblanco floorVal, stitchData, floorVal, stitchData); 744ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }", 745ce6a354e121915c2925e545e7df2929492d69d50senorblanco floorVal, stitchData, floorVal, stitchData); 746ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }", 747ce6a354e121915c2925e545e7df2929492d69d50senorblanco floorVal, stitchData, floorVal, stitchData); 748e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 749e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 750e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Get texture coordinates and normalize 751ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / vec4(256.0));\n", 752ce6a354e121915c2925e545e7df2929492d69d50senorblanco floorVal, floorVal); 753e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 754e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Get permutation for x 755e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com { 756e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkString xCoords(""); 757ce6a354e121915c2925e545e7df2929492d69d50senorblanco xCoords.appendf("vec2(%s.x, 0.5)", floorVal); 758e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 759d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx); 76030ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType); 761d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.append(".r;"); 762e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 763e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 764e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Get permutation for x + 1 765e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com { 766e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkString xCoords(""); 767ce6a354e121915c2925e545e7df2929492d69d50senorblanco xCoords.appendf("vec2(%s.z, 0.5)", floorVal); 768e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 769d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf("\n\t%s.y = ", latticeIdx); 77030ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType); 771d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.append(".r;"); 772e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 773e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 774344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org#if defined(SK_BUILD_FOR_ANDROID) 775344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org // Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3). 776344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org // The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit 777344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org // value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725 778344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org // (or 0.484368 here). The following rounding operation prevents these precision issues from 779344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org // affecting the result of the noise by making sure that we only have multiples of 1/255. 780344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org // (Note that 1/255 is about 0.003921569, which is the value used here). 781344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org noiseCode.appendf("\n\t%s = floor(%s * vec2(255.0) + vec2(0.5)) * vec2(0.003921569);", 782344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org latticeIdx, latticeIdx); 783344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org#endif 784344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org 785e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Get (x,y) coordinates with the permutated x 786ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseCode.appendf("\n\tvec4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal); 787e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 788d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf("\n\n\tvec2 %s;", uv); 789e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Compute u, at offset (0,0) 790e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com { 791e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkString latticeCoords(""); 792ce6a354e121915c2925e545e7df2929492d69d50senorblanco latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord); 793d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf("\n\tvec4 %s = ", lattice); 79430ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), 795d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com kVec2f_GrSLType); 796d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf(".bgra;\n\t%s.x = ", uv); 797d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); 798e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 799e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 800d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal); 801e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Compute v, at offset (-1,0) 802e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com { 803e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkString latticeCoords(""); 804ce6a354e121915c2925e545e7df2929492d69d50senorblanco latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord); 805344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org noiseCode.append("\n\tlattice = "); 80630ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), 807d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com kVec2f_GrSLType); 808d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf(".bgra;\n\t%s.y = ", uv); 809d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); 810e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 811e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 812e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Compute 'a' as a linear interpolation of 'u' and 'v' 813d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf("\n\tvec2 %s;", ab); 814d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth); 815e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 816d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal); 817e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Compute v, at offset (-1,-1) 818e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com { 819e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkString latticeCoords(""); 820ce6a354e121915c2925e545e7df2929492d69d50senorblanco latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord); 821344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org noiseCode.append("\n\tlattice = "); 82230ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), 823d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com kVec2f_GrSLType); 824d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf(".bgra;\n\t%s.y = ", uv); 825d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); 826e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 827e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 828d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf("\n\t%s.x += 1.0;", fractVal); 829e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Compute u, at offset (0,-1) 830e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com { 831e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkString latticeCoords(""); 832ce6a354e121915c2925e545e7df2929492d69d50senorblanco latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord); 833344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org noiseCode.append("\n\tlattice = "); 83430ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), 835d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com kVec2f_GrSLType); 836d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf(".bgra;\n\t%s.x = ", uv); 837d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); 838e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 839e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 840e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Compute 'b' as a linear interpolation of 'u' and 'v' 841d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth); 842e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Compute the noise as a linear interpolation of 'a' and 'b' 843d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth); 844d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com 845d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com SkString noiseFuncName; 846d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com if (fStitchTiles) { 84730ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->emitFunction(kFloat_GrSLType, 84874a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs), 84974a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName); 850d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com } else { 85130ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->emitFunction(kFloat_GrSLType, 85274a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs), 85374a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName); 854d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com } 855e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 856d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com // There are rounding errors if the floor operation is not performed here 85730ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;", 858ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco noiseVec, vCoords.c_str(), baseFrequencyUni); 859e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 860d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com // Clear the color accumulator 86130ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", outputColor); 862e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 863e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com if (fStitchTiles) { 864d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com // Set up TurbulenceInitial stitch values. 86530ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\tvec2 %s = %s;", stitchData, stitchDataUni); 866e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 867e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 86830ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\tfloat %s = 1.0;", ratio); 869d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com 870d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com // Loop over all octaves 87130ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\tfor (int octave = 0; octave < %d; ++octave) {", fNumOctaves); 872d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com 87330ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\t\t%s += ", outputColor); 874d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com if (fType != SkPerlinNoiseShader::kFractalNoise_Type) { 87530ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("abs("); 876d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com } 877d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com if (fStitchTiles) { 87830ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf( 879d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s)," 880d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))", 881d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData, 882d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData, 883d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData, 884d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData); 885d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com } else { 88630ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf( 887d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s)," 888d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))", 889d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseFuncName.c_str(), chanCoordR, noiseVec, 890d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseFuncName.c_str(), chanCoordG, noiseVec, 891d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseFuncName.c_str(), chanCoordB, noiseVec, 892d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseFuncName.c_str(), chanCoordA, noiseVec); 893d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com } 894d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com if (fType != SkPerlinNoiseShader::kFractalNoise_Type) { 89530ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf(")"); // end of "abs(" 896d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com } 89730ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf(" * %s;", ratio); 898d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com 89930ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec); 90030ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio); 901d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com 902d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com if (fStitchTiles) { 90330ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData); 904d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com } 90530ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves 906e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 907e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com if (fType == SkPerlinNoiseShader::kFractalNoise_Type) { 908e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2 909e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // by fractalNoise and (turbulenceFunctionResult) by turbulence. 91030ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);", outputColor, outputColor); 911e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 912e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 91330ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\t%s.a *= %s;", outputColor, alphaUni); 914e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 915e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Clamp values 91630ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", outputColor, outputColor); 917e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 918e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Pre-multiply the result 91930ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n", 920e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com outputColor, outputColor, outputColor, outputColor); 921e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 922e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 923b0a8a377f832c59cee939ad721e1f87d378b7142joshualittvoid GrGLPerlinNoise::GenKey(const GrProcessor& processor, const GrGLCaps&, 924b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrProcessorKeyBuilder* b) { 925b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrPerlinNoiseEffect& turbulence = processor.cast<GrPerlinNoiseEffect>(); 926e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 92763e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon uint32_t key = turbulence.numOctaves(); 928e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 929e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com key = key << 3; // Make room for next 3 bits 930e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 931e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com switch (turbulence.type()) { 932e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com case SkPerlinNoiseShader::kFractalNoise_Type: 933e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com key |= 0x1; 934e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com break; 935e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com case SkPerlinNoiseShader::kTurbulence_Type: 936e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com key |= 0x2; 937e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com break; 938e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com default: 939e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // leave key at 0 940e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com break; 941e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 942e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 943e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com if (turbulence.stitchTiles()) { 944e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com key |= 0x4; // Flip the 3rd bit if tile stitching is on 945e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 946e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 94763e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon b->add32(key); 948e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 949e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 950b0a8a377f832c59cee939ad721e1f87d378b7142joshualittvoid GrGLPerlinNoise::setData(const GrGLProgramDataManager& pdman, const GrProcessor& processor) { 951b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt INHERITED::setData(pdman, processor); 952f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco 953b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrPerlinNoiseEffect& turbulence = processor.cast<GrPerlinNoiseEffect>(); 954e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 955e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const SkVector& baseFrequency = turbulence.baseFrequency(); 9567510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY); 9577510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set1f(fAlphaUni, SkScalarDiv(SkIntToScalar(turbulence.alpha()), SkIntToScalar(255))); 958e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 9594775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com if (turbulence.stitchTiles()) { 9604775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com const SkPerlinNoiseShader::StitchData& stitchData = turbulence.stitchData(); 9617510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth), 9629839320ae17ab1c2182dc144db5ba94caa1bde56commit-bot@chromium.org SkIntToScalar(stitchData.fHeight)); 9634775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com } 9644775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com} 9654775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com 966e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com///////////////////////////////////////////////////////////////////// 967e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 968b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool SkPerlinNoiseShader::asFragmentProcessor(GrContext* context, const SkPaint& paint, 969b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const SkMatrix* externalLocalMatrix, 970b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrColor* paintColor, GrFragmentProcessor** fp) const { 97149f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(context); 9729de5b514d38c5b36066bcdc14fba2f7e5196d372dandov 97383d081ae1d731b5039e99823620f5e287542ee39bsalomon *paintColor = SkColor2GrColorJustAlpha(paint.getColor()); 974ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco 97596fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org SkMatrix localMatrix = this->getLocalMatrix(); 97696fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org if (externalLocalMatrix) { 97796fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org localMatrix.preConcat(*externalLocalMatrix); 97896fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org } 97996fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org 980ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkMatrix matrix = context->getMatrix(); 981ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco matrix.preConcat(localMatrix); 982ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco 983c2a0ea6418988d4bcc0719f99b1a110cecd08679commit-bot@chromium.org if (0 == fNumOctaves) { 984c2a0ea6418988d4bcc0719f99b1a110cecd08679commit-bot@chromium.org SkColor clearColor = 0; 985c2a0ea6418988d4bcc0719f99b1a110cecd08679commit-bot@chromium.org if (kFractalNoise_Type == fType) { 986c2a0ea6418988d4bcc0719f99b1a110cecd08679commit-bot@chromium.org clearColor = SkColorSetARGB(paint.getAlpha() / 2, 127, 127, 127); 987c2a0ea6418988d4bcc0719f99b1a110cecd08679commit-bot@chromium.org } 988c2a0ea6418988d4bcc0719f99b1a110cecd08679commit-bot@chromium.org SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter( 989c2a0ea6418988d4bcc0719f99b1a110cecd08679commit-bot@chromium.org clearColor, SkXfermode::kSrc_Mode)); 990b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt *fp = cf->asFragmentProcessor(context); 9919de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return true; 992c2a0ea6418988d4bcc0719f99b1a110cecd08679commit-bot@chromium.org } 993c2a0ea6418988d4bcc0719f99b1a110cecd08679commit-bot@chromium.org 994e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Either we don't stitch tiles, either we have a valid tile size 995e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkASSERT(!fStitchTiles || !fTileSize.isEmpty()); 996e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 997b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkPerlinNoiseShader::PaintingData* paintingData = 998b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkNEW_ARGS(PaintingData, (fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY, matrix)); 999e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com GrTexture* permutationsTexture = GrLockAndRefCachedBitmapTexture( 1000ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco context, paintingData->getPermutationsBitmap(), NULL); 1001e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com GrTexture* noiseTexture = GrLockAndRefCachedBitmapTexture( 1002ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco context, paintingData->getNoiseBitmap(), NULL); 1003ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco 1004ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkMatrix m = context->getMatrix(); 1005ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1); 1006ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1); 100749f085dddff10473b6ebf832a974288300224e60bsalomon if ((permutationsTexture) && (noiseTexture)) { 1008b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt *fp = GrPerlinNoiseEffect::Create(fType, 1009b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt fNumOctaves, 1010b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt fStitchTiles, 1011b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt paintingData, 1012b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt permutationsTexture, noiseTexture, 1013b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt m, paint.getAlpha()); 1014ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco } else { 1015ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkDELETE(paintingData); 1016b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt *fp = NULL; 1017ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco } 1018e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 1019e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Unlock immediately, this is not great, but we don't have a way of 1020e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // knowing when else to unlock it currently. TODO: Remove this when 1021e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // unref becomes the unlock replacement for all types of textures. 102249f085dddff10473b6ebf832a974288300224e60bsalomon if (permutationsTexture) { 1023e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com GrUnlockAndUnrefCachedBitmapTexture(permutationsTexture); 1024e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 102549f085dddff10473b6ebf832a974288300224e60bsalomon if (noiseTexture) { 1026e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com GrUnlockAndUnrefCachedBitmapTexture(noiseTexture); 1027e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 1028e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 10299de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return true; 1030e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 1031e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 1032e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#else 1033e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 1034b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool SkPerlinNoiseShader::asFragmentProcessor(GrContext*, const SkPaint&, const SkMatrix*, GrColor*, 1035b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrFragmentProcessor**) const { 1036e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkDEBUGFAIL("Should not call in GPU-less build"); 10379de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return false; 1038e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 1039e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 1040e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#endif 1041e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 10420f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING 1043e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comvoid SkPerlinNoiseShader::toString(SkString* str) const { 1044e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append("SkPerlinNoiseShader: ("); 1045e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 1046e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append("type: "); 1047e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com switch (fType) { 1048e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com case kFractalNoise_Type: 1049e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append("\"fractal noise\""); 1050e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com break; 1051e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com case kTurbulence_Type: 1052e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append("\"turbulence\""); 1053e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com break; 1054e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com default: 1055e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append("\"unknown\""); 1056e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com break; 1057e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 1058e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append(" base frequency: ("); 1059e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->appendScalar(fBaseFrequencyX); 1060e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append(", "); 1061e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->appendScalar(fBaseFrequencyY); 1062e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append(") number of octaves: "); 1063e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->appendS32(fNumOctaves); 1064e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append(" seed: "); 1065e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->appendScalar(fSeed); 1066e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append(" stitch tiles: "); 1067e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append(fStitchTiles ? "true " : "false "); 1068e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 1069e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com this->INHERITED::toString(str); 1070e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 1071e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append(")"); 1072e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 1073e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#endif 1074