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" 20605dd0fbce9dbb2a0d3313e13e161f2bd54870d7egdaniel#include "GrInvariantOutput.h" 21eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "SkGr.h" 22b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "gl/GrGLProcessor.h" 2330ba436f04e61d4505fb854d5fc56079636e0788joshualitt#include "gl/builders/GrGLProgramBuilder.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 53e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} // end namespace 54e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 55e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comstruct SkPerlinNoiseShader::StitchData { 56e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com StitchData() 57e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com : fWidth(0) 58e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com , fWrapX(0) 59e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com , fHeight(0) 60e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com , fWrapY(0) 61e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com {} 62e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 63e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com bool operator==(const StitchData& other) const { 64e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com return fWidth == other.fWidth && 65e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fWrapX == other.fWrapX && 66e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fHeight == other.fHeight && 67e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fWrapY == other.fWrapY; 68e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 69e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 70e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int fWidth; // How much to subtract to wrap for stitching. 71e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int fWrapX; // Minimum value to wrap. 72e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int fHeight; 73e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int fWrapY; 74e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}; 75e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 76e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comstruct SkPerlinNoiseShader::PaintingData { 77fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org PaintingData(const SkISize& tileSize, SkScalar seed, 78ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkScalar baseFrequencyX, SkScalar baseFrequencyY, 79ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco const SkMatrix& matrix) 80e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com { 8111fa2247b747eb75e2f158dc7571d458ed6c0115reed SkVector vec[2] = { 8211fa2247b747eb75e2f158dc7571d458ed6c0115reed { SkScalarInvert(baseFrequencyX), SkScalarInvert(baseFrequencyY) }, 8311fa2247b747eb75e2f158dc7571d458ed6c0115reed { SkIntToScalar(tileSize.fWidth), SkIntToScalar(tileSize.fHeight) }, 8411fa2247b747eb75e2f158dc7571d458ed6c0115reed }; 8511fa2247b747eb75e2f158dc7571d458ed6c0115reed matrix.mapVectors(vec, 2); 8611fa2247b747eb75e2f158dc7571d458ed6c0115reed 8711fa2247b747eb75e2f158dc7571d458ed6c0115reed fBaseFrequency.set(SkScalarInvert(vec[0].fX), SkScalarInvert(vec[0].fY)); 8811fa2247b747eb75e2f158dc7571d458ed6c0115reed fTileSize.set(SkScalarRoundToInt(vec[1].fX), SkScalarRoundToInt(vec[1].fY)); 89fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org this->init(seed); 90fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org if (!fTileSize.isEmpty()) { 91fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org this->stitch(); 92fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org } 93fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org 94f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco#if SK_SUPPORT_GPU 95a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org fPermutationsBitmap.setInfo(SkImageInfo::MakeA8(kBlockSize, 1)); 96fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org fPermutationsBitmap.setPixels(fLatticeSelector); 97fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org 98a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org fNoiseBitmap.setInfo(SkImageInfo::MakeN32Premul(kBlockSize, 4)); 99fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org fNoiseBitmap.setPixels(fNoise[0][0]); 100fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org#endif 101e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 102e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 103e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int fSeed; 104e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com uint8_t fLatticeSelector[kBlockSize]; 105e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com uint16_t fNoise[4][kBlockSize][2]; 106e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkPoint fGradient[4][kBlockSize]; 107e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkISize fTileSize; 108e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkVector fBaseFrequency; 109e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com StitchData fStitchDataInit; 110e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 111e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comprivate: 112e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 113f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco#if SK_SUPPORT_GPU 114fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org SkBitmap fPermutationsBitmap; 115fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org SkBitmap fNoiseBitmap; 116fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org#endif 117e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 118e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com inline int random() { 119e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com static const int gRandAmplitude = 16807; // 7**5; primitive root of m 120e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com static const int gRandQ = 127773; // m / a 121e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com static const int gRandR = 2836; // m % a 122e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 123e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int result = gRandAmplitude * (fSeed % gRandQ) - gRandR * (fSeed / gRandQ); 124e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com if (result <= 0) 125e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com result += kRandMaximum; 126e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fSeed = result; 127e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com return result; 128e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 129e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 130fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org // Only called once. Could be part of the constructor. 131e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com void init(SkScalar seed) 132e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com { 133e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com static const SkScalar gInvBlockSizef = SkScalarInvert(SkIntToScalar(kBlockSize)); 134e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 135857e320300372dab938c0dbffadc3c2c8a893b92senorblanco@chromium.org // According to the SVG spec, we must truncate (not round) the seed value. 136857e320300372dab938c0dbffadc3c2c8a893b92senorblanco@chromium.org fSeed = SkScalarTruncToInt(seed); 137e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // The seed value clamp to the range [1, kRandMaximum - 1]. 138e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com if (fSeed <= 0) { 139e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fSeed = -(fSeed % (kRandMaximum - 1)) + 1; 140e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 141e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com if (fSeed > kRandMaximum - 1) { 142e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fSeed = kRandMaximum - 1; 143e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 144e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int channel = 0; channel < 4; ++channel) { 145e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int i = 0; i < kBlockSize; ++i) { 146e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fLatticeSelector[i] = i; 147e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fNoise[channel][i][0] = (random() % (2 * kBlockSize)); 148e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fNoise[channel][i][1] = (random() % (2 * kBlockSize)); 149e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 150e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 151e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int i = kBlockSize - 1; i > 0; --i) { 152e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int k = fLatticeSelector[i]; 153e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int j = random() % kBlockSize; 154e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkASSERT(j >= 0); 155e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkASSERT(j < kBlockSize); 156e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fLatticeSelector[i] = fLatticeSelector[j]; 157e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fLatticeSelector[j] = k; 158e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 159e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 160e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Perform the permutations now 161e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com { 162e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Copy noise data 163e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com uint16_t noise[4][kBlockSize][2]; 164e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int i = 0; i < kBlockSize; ++i) { 165e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int channel = 0; channel < 4; ++channel) { 166e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int j = 0; j < 2; ++j) { 167e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com noise[channel][i][j] = fNoise[channel][i][j]; 168e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 169e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 170e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 171e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Do permutations on noise data 172e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int i = 0; i < kBlockSize; ++i) { 173e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int channel = 0; channel < 4; ++channel) { 174e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int j = 0; j < 2; ++j) { 175e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fNoise[channel][i][j] = noise[channel][fLatticeSelector[i]][j]; 176e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 177e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 178e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 179e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 180e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 181e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Half of the largest possible value for 16 bit unsigned int 1824b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org static const SkScalar gHalfMax16bits = 32767.5f; 183e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 184e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Compute gradients from permutated noise data 185e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int channel = 0; channel < 4; ++channel) { 186e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int i = 0; i < kBlockSize; ++i) { 187e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fGradient[channel][i] = SkPoint::Make( 188e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalarMul(SkIntToScalar(fNoise[channel][i][0] - kBlockSize), 189e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com gInvBlockSizef), 190cff0243b0ff1de25b3d99e2bf15a30c0e0a31261skia.committer@gmail.com SkScalarMul(SkIntToScalar(fNoise[channel][i][1] - kBlockSize), 191e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com gInvBlockSizef)); 192e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fGradient[channel][i].normalize(); 193e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Put the normalized gradient back into the noise data 194e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fNoise[channel][i][0] = SkScalarRoundToInt(SkScalarMul( 195d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com fGradient[channel][i].fX + SK_Scalar1, gHalfMax16bits)); 196e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fNoise[channel][i][1] = SkScalarRoundToInt(SkScalarMul( 197d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com fGradient[channel][i].fY + SK_Scalar1, gHalfMax16bits)); 198e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 199e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 200e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 201e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 202fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org // Only called once. Could be part of the constructor. 203e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com void stitch() { 204e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar tileWidth = SkIntToScalar(fTileSize.width()); 205e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar tileHeight = SkIntToScalar(fTileSize.height()); 206e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkASSERT(tileWidth > 0 && tileHeight > 0); 207e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // When stitching tiled turbulence, the frequencies must be adjusted 208e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // so that the tile borders will be continuous. 209e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com if (fBaseFrequency.fX) { 2108015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com SkScalar lowFrequencx = 2118015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com SkScalarFloorToScalar(tileWidth * fBaseFrequency.fX) / tileWidth; 2128015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com SkScalar highFrequencx = 2138015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com SkScalarCeilToScalar(tileWidth * fBaseFrequency.fX) / tileWidth; 214e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // BaseFrequency should be non-negative according to the standard. 21580ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed if (fBaseFrequency.fX / lowFrequencx < highFrequencx / fBaseFrequency.fX) { 216e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fBaseFrequency.fX = lowFrequencx; 217e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } else { 218e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fBaseFrequency.fX = highFrequencx; 219e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 220e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 221e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com if (fBaseFrequency.fY) { 2228015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com SkScalar lowFrequency = 2238015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com SkScalarFloorToScalar(tileHeight * fBaseFrequency.fY) / tileHeight; 2248015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com SkScalar highFrequency = 2258015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com SkScalarCeilToScalar(tileHeight * fBaseFrequency.fY) / tileHeight; 22680ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed if (fBaseFrequency.fY / lowFrequency < highFrequency / fBaseFrequency.fY) { 227e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fBaseFrequency.fY = lowFrequency; 228e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } else { 229e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fBaseFrequency.fY = highFrequency; 230e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 231e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 232e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Set up TurbulenceInitial stitch values. 233e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fStitchDataInit.fWidth = 2348015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com SkScalarRoundToInt(tileWidth * fBaseFrequency.fX); 235e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fStitchDataInit.fWrapX = kPerlinNoise + fStitchDataInit.fWidth; 236e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fStitchDataInit.fHeight = 2378015cdd8fa5694e52b70e728bcdc6b35d739b819reed@google.com SkScalarRoundToInt(tileHeight * fBaseFrequency.fY); 238e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fStitchDataInit.fWrapY = kPerlinNoise + fStitchDataInit.fHeight; 239e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 240e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 241fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.orgpublic: 242e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 243f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco#if SK_SUPPORT_GPU 244fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org const SkBitmap& getPermutationsBitmap() const { return fPermutationsBitmap; } 245fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org 246fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org const SkBitmap& getNoiseBitmap() const { return fNoiseBitmap; } 247fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org#endif 248e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}; 249e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 250e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comSkShader* SkPerlinNoiseShader::CreateFractalNoise(SkScalar baseFrequencyX, SkScalar baseFrequencyY, 251e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int numOctaves, SkScalar seed, 252e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const SkISize* tileSize) { 253e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com return SkNEW_ARGS(SkPerlinNoiseShader, (kFractalNoise_Type, baseFrequencyX, baseFrequencyY, 254e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com numOctaves, seed, tileSize)); 255e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 256e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 2579fbbcca1c958e6df2cff24d3ccdb7ebd89b8486bcommit-bot@chromium.orgSkShader* SkPerlinNoiseShader::CreateTurbulence(SkScalar baseFrequencyX, SkScalar baseFrequencyY, 258e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int numOctaves, SkScalar seed, 259e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const SkISize* tileSize) { 260e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com return SkNEW_ARGS(SkPerlinNoiseShader, (kTurbulence_Type, baseFrequencyX, baseFrequencyY, 261e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com numOctaves, seed, tileSize)); 262e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 263e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 264e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comSkPerlinNoiseShader::SkPerlinNoiseShader(SkPerlinNoiseShader::Type type, 265e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar baseFrequencyX, 266e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar baseFrequencyY, 267e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int numOctaves, 268e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar seed, 269e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const SkISize* tileSize) 270e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com : fType(type) 271e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com , fBaseFrequencyX(baseFrequencyX) 272e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com , fBaseFrequencyY(baseFrequencyY) 273ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org , fNumOctaves(numOctaves > 255 ? 255 : numOctaves/*[0,255] octaves allowed*/) 274e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com , fSeed(seed) 275fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org , fTileSize(NULL == tileSize ? SkISize::Make(0, 0) : *tileSize) 276fd5c9a6e04ba31a82670d281b03b9c4a3f9b6e3ccommit-bot@chromium.org , fStitchTiles(!fTileSize.isEmpty()) 277e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com{ 278e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkASSERT(numOctaves >= 0 && numOctaves < 256); 279e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 280e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 281e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comSkPerlinNoiseShader::~SkPerlinNoiseShader() { 282e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 283e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 2849fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkPerlinNoiseShader::CreateProc(SkReadBuffer& buffer) { 2859fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed Type type = (Type)buffer.readInt(); 2869fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkScalar freqX = buffer.readScalar(); 2879fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkScalar freqY = buffer.readScalar(); 2889fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed int octaves = buffer.readInt(); 2899fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkScalar seed = buffer.readScalar(); 2909fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkISize tileSize; 2919fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed tileSize.fWidth = buffer.readInt(); 2929fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed tileSize.fHeight = buffer.readInt(); 2939fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 2949fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed switch (type) { 2959fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed case kFractalNoise_Type: 2969fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed return SkPerlinNoiseShader::CreateFractalNoise(freqX, freqY, octaves, seed, &tileSize); 2979fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed case kTurbulence_Type: 2989fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed return SkPerlinNoiseShader::CreateTubulence(freqX, freqY, octaves, seed, &tileSize); 2999fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed default: 3009fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed return NULL; 3019fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 3029fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 3039fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 3048b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkPerlinNoiseShader::flatten(SkWriteBuffer& buffer) const { 305e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com buffer.writeInt((int) fType); 306e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com buffer.writeScalar(fBaseFrequencyX); 307e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com buffer.writeScalar(fBaseFrequencyY); 308e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com buffer.writeInt(fNumOctaves); 309e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com buffer.writeScalar(fSeed); 310e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com buffer.writeInt(fTileSize.fWidth); 311e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com buffer.writeInt(fTileSize.fHeight); 312e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 313e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 31487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::noise2D( 315ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco int channel, const StitchData& stitchData, const SkPoint& noiseVector) const { 316e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com struct Noise { 317e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int noisePositionIntegerValue; 318ce6a354e121915c2925e545e7df2929492d69d50senorblanco int nextNoisePositionIntegerValue; 319e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar noisePositionFractionValue; 320e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com Noise(SkScalar component) 321e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com { 322e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar position = component + kPerlinNoise; 323e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com noisePositionIntegerValue = SkScalarFloorToInt(position); 324e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com noisePositionFractionValue = position - SkIntToScalar(noisePositionIntegerValue); 325ce6a354e121915c2925e545e7df2929492d69d50senorblanco nextNoisePositionIntegerValue = noisePositionIntegerValue + 1; 326e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 327e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com }; 328e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com Noise noiseX(noiseVector.x()); 329e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com Noise noiseY(noiseVector.y()); 330e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar u, v; 33187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader); 332e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // If stitching, adjust lattice points accordingly. 33387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (perlinNoiseShader.fStitchTiles) { 334e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com noiseX.noisePositionIntegerValue = 335e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth); 336e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com noiseY.noisePositionIntegerValue = 337e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight); 338ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseX.nextNoisePositionIntegerValue = 339ce6a354e121915c2925e545e7df2929492d69d50senorblanco checkNoise(noiseX.nextNoisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth); 340ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseY.nextNoisePositionIntegerValue = 341ce6a354e121915c2925e545e7df2929492d69d50senorblanco checkNoise(noiseY.nextNoisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight); 342e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 343e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com noiseX.noisePositionIntegerValue &= kBlockMask; 344e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com noiseY.noisePositionIntegerValue &= kBlockMask; 345ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseX.nextNoisePositionIntegerValue &= kBlockMask; 346ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseY.nextNoisePositionIntegerValue &= kBlockMask; 347ce6a354e121915c2925e545e7df2929492d69d50senorblanco int i = 348ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco fPaintingData->fLatticeSelector[noiseX.noisePositionIntegerValue]; 349ce6a354e121915c2925e545e7df2929492d69d50senorblanco int j = 350ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco fPaintingData->fLatticeSelector[noiseX.nextNoisePositionIntegerValue]; 351ce6a354e121915c2925e545e7df2929492d69d50senorblanco int b00 = (i + noiseY.noisePositionIntegerValue) & kBlockMask; 352ce6a354e121915c2925e545e7df2929492d69d50senorblanco int b10 = (j + noiseY.noisePositionIntegerValue) & kBlockMask; 353ce6a354e121915c2925e545e7df2929492d69d50senorblanco int b01 = (i + noiseY.nextNoisePositionIntegerValue) & kBlockMask; 354ce6a354e121915c2925e545e7df2929492d69d50senorblanco int b11 = (j + noiseY.nextNoisePositionIntegerValue) & kBlockMask; 355e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar sx = smoothCurve(noiseX.noisePositionFractionValue); 356e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar sy = smoothCurve(noiseY.noisePositionFractionValue); 357e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement 358e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkPoint fractionValue = SkPoint::Make(noiseX.noisePositionFractionValue, 359e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com noiseY.noisePositionFractionValue); // Offset (0,0) 360ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco u = fPaintingData->fGradient[channel][b00].dot(fractionValue); 361e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fractionValue.fX -= SK_Scalar1; // Offset (-1,0) 362ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco v = fPaintingData->fGradient[channel][b10].dot(fractionValue); 363e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar a = SkScalarInterp(u, v, sx); 364e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fractionValue.fY -= SK_Scalar1; // Offset (-1,-1) 365ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco v = fPaintingData->fGradient[channel][b11].dot(fractionValue); 366e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1) 367ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco u = fPaintingData->fGradient[channel][b01].dot(fractionValue); 368e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar b = SkScalarInterp(u, v, sx); 369e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com return SkScalarInterp(a, b, sy); 370e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 371e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 37287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::calculateTurbulenceValueForPoint( 373ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco int channel, StitchData& stitchData, const SkPoint& point) const { 37487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader); 37587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (perlinNoiseShader.fStitchTiles) { 376e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Set up TurbulenceInitial stitch values. 377ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco stitchData = fPaintingData->fStitchDataInit; 378e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 379e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar turbulenceFunctionResult = 0; 380ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkPoint noiseVector(SkPoint::Make(SkScalarMul(point.x(), fPaintingData->fBaseFrequency.fX), 381ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkScalarMul(point.y(), fPaintingData->fBaseFrequency.fY))); 382e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar ratio = SK_Scalar1; 38387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) { 384ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkScalar noise = noise2D(channel, stitchData, noiseVector); 38580ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed SkScalar numer = (perlinNoiseShader.fType == kFractalNoise_Type) ? 38680ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed noise : SkScalarAbs(noise); 38780ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed turbulenceFunctionResult += numer / ratio; 388e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com noiseVector.fX *= 2; 389e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com noiseVector.fY *= 2; 390e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com ratio *= 2; 39187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (perlinNoiseShader.fStitchTiles) { 392e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Update stitch values 393e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com stitchData.fWidth *= 2; 394e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com stitchData.fWrapX = stitchData.fWidth + kPerlinNoise; 395e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com stitchData.fHeight *= 2; 396e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com stitchData.fWrapY = stitchData.fHeight + kPerlinNoise; 397e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 398e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 399e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 400e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2 401e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // by fractalNoise and (turbulenceFunctionResult) by turbulence. 40287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (perlinNoiseShader.fType == kFractalNoise_Type) { 403e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com turbulenceFunctionResult = 404e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalarMul(turbulenceFunctionResult, SK_ScalarHalf) + SK_ScalarHalf; 405e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 406e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 407e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com if (channel == 3) { // Scale alpha by paint value 40880ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed turbulenceFunctionResult *= SkIntToScalar(getPaintAlpha()) / 255; 409e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 410e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 411e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Clamp result 412e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1); 413e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 414e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 41587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkPMColor SkPerlinNoiseShader::PerlinNoiseShaderContext::shade( 41687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const SkPoint& point, StitchData& stitchData) const { 417e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkPoint newPoint; 418a8d95f899bf3fe404d3cd5c357531ff852c15b29senorblanco@chromium.org fMatrix.mapPoints(&newPoint, &point, 1); 419e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com newPoint.fX = SkScalarRoundToScalar(newPoint.fX); 420e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com newPoint.fY = SkScalarRoundToScalar(newPoint.fY); 421e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 422e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com U8CPU rgba[4]; 423e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int channel = 3; channel >= 0; --channel) { 424e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com rgba[channel] = SkScalarFloorToInt(255 * 425ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco calculateTurbulenceValueForPoint(channel, stitchData, newPoint)); 426e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 427e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]); 428e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 429e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 430ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.orgSkShader::Context* SkPerlinNoiseShader::onCreateContext(const ContextRec& rec, 431ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org void* storage) const { 432e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org return SkNEW_PLACEMENT_ARGS(storage, PerlinNoiseShaderContext, (*this, rec)); 43387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org} 43487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 43587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgsize_t SkPerlinNoiseShader::contextSize() const { 43687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org return sizeof(PerlinNoiseShaderContext); 43787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org} 43887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 43987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkPerlinNoiseShader::PerlinNoiseShaderContext::PerlinNoiseShaderContext( 440e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org const SkPerlinNoiseShader& shader, const ContextRec& rec) 441e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org : INHERITED(shader, rec) 44287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org{ 443e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org SkMatrix newMatrix = *rec.fMatrix; 444b67b8e6052bf5567eb3f9726dda99a6b260dfb05reed@google.com newMatrix.preConcat(shader.getLocalMatrix()); 445b67b8e6052bf5567eb3f9726dda99a6b260dfb05reed@google.com if (rec.fLocalMatrix) { 446b67b8e6052bf5567eb3f9726dda99a6b260dfb05reed@google.com newMatrix.preConcat(*rec.fLocalMatrix); 447b67b8e6052bf5567eb3f9726dda99a6b260dfb05reed@google.com } 448a8d95f899bf3fe404d3cd5c357531ff852c15b29senorblanco@chromium.org // This (1,1) translation is due to WebKit's 1 based coordinates for the noise 449a8d95f899bf3fe404d3cd5c357531ff852c15b29senorblanco@chromium.org // (as opposed to 0 based, usually). The same adjustment is in the setData() function. 450ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco fMatrix.setTranslate(-newMatrix.getTranslateX() + SK_Scalar1, -newMatrix.getTranslateY() + SK_Scalar1); 451ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco fPaintingData = SkNEW_ARGS(PaintingData, (shader.fTileSize, shader.fSeed, shader.fBaseFrequencyX, shader.fBaseFrequencyY, newMatrix)); 452ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco} 453ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco 454ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblancoSkPerlinNoiseShader::PerlinNoiseShaderContext::~PerlinNoiseShaderContext() { 455ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkDELETE(fPaintingData); 456e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 457e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 45887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgvoid SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan( 45987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org int x, int y, SkPMColor result[], int count) { 460e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y)); 461e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com StitchData stitchData; 462e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int i = 0; i < count; ++i) { 463e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com result[i] = shade(point, stitchData); 464e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com point.fX += SK_Scalar1; 465e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 466e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 467e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 46887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgvoid SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan16( 46987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org int x, int y, uint16_t result[], int count) { 470e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y)); 471e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com StitchData stitchData; 472e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com DITHER_565_SCAN(y); 473e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com for (int i = 0; i < count; ++i) { 474e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com unsigned dither = DITHER_VALUE(x); 475e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com result[i] = SkDitherRGB32To565(shade(point, stitchData), dither); 476e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com DITHER_INC_X(x); 477e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com point.fX += SK_Scalar1; 478e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 479e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 480e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 481e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com///////////////////////////////////////////////////////////////////// 482e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 483344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org#if SK_SUPPORT_GPU 484e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 485b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GrGLPerlinNoise : public GrGLFragmentProcessor { 4864775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.compublic: 487eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt GrGLPerlinNoise(const GrProcessor&); 4884775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com virtual ~GrGLPerlinNoise() {} 489e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 4901598899975ecc85b003a59740b588d1ddbcedb09joshualitt virtual void emitCode(GrGLFPBuilder*, 491b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrFragmentProcessor&, 492e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* outputColor, 493e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* inputColor, 49477af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com const TransformedCoordsArray&, 49536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein const TextureSamplerArray&) override; 496e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 49736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void setData(const GrGLProgramDataManager&, const GrProcessor&) override; 4984775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com 499cfc18867d982119d9dc2888bf09f1093012daaddjvanverth static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder* b); 5004775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com 501f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblancoprivate: 502e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 5037510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen GrGLProgramDataManager::UniformHandle fStitchDataUni; 5047510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen SkPerlinNoiseShader::Type fType; 5057510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen bool fStitchTiles; 5067510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen int fNumOctaves; 5077510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen GrGLProgramDataManager::UniformHandle fBaseFrequencyUni; 5087510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen GrGLProgramDataManager::UniformHandle fAlphaUni; 509e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 510e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comprivate: 511b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt typedef GrGLFragmentProcessor INHERITED; 512e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}; 513e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 514e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com///////////////////////////////////////////////////////////////////// 515e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 516b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GrPerlinNoiseEffect : public GrFragmentProcessor { 517e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.compublic: 518b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt static GrFragmentProcessor* Create(SkPerlinNoiseShader::Type type, 519b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt int numOctaves, bool stitchTiles, 520b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkPerlinNoiseShader::PaintingData* paintingData, 521b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrTexture* permutationsTexture, GrTexture* noiseTexture, 522b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const SkMatrix& matrix, uint8_t alpha) { 52355fad7af61c21d502acb9891d631e8aa29e3628cbsalomon return SkNEW_ARGS(GrPerlinNoiseEffect, (type, numOctaves, stitchTiles, paintingData, 52455fad7af61c21d502acb9891d631e8aa29e3628cbsalomon permutationsTexture, noiseTexture, matrix, alpha)); 525e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 526e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 527ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco virtual ~GrPerlinNoiseEffect() { 528ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkDELETE(fPaintingData); 529ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco } 530e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 53136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein const char* name() const override { return "PerlinNoise"; } 532eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 533cfc18867d982119d9dc2888bf09f1093012daaddjvanverth virtual void getGLProcessorKey(const GrGLSLCaps& caps, 53436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein GrProcessorKeyBuilder* b) const override { 535eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt GrGLPerlinNoise::GenKey(*this, caps, b); 536eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt } 537eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 53836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein GrGLFragmentProcessor* createGLInstance() const override { 539eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt return SkNEW_ARGS(GrGLPerlinNoise, (*this)); 540e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 541eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 542ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco const SkPerlinNoiseShader::StitchData& stitchData() const { return fPaintingData->fStitchDataInit; } 543e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 544f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco SkPerlinNoiseShader::Type type() const { return fType; } 545f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco bool stitchTiles() const { return fStitchTiles; } 546ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; } 547f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco int numOctaves() const { return fNumOctaves; } 548f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); } 549f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco uint8_t alpha() const { return fAlpha; } 550f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco 551e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comprivate: 55236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein bool onIsEqual(const GrFragmentProcessor& sBase) const override { 55349586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt const GrPerlinNoiseEffect& s = sBase.cast<GrPerlinNoiseEffect>(); 554f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco return fType == s.fType && 555ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency && 556f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco fNumOctaves == s.fNumOctaves && 557f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco fStitchTiles == s.fStitchTiles && 558f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco fAlpha == s.fAlpha && 559ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco fPaintingData->fStitchDataInit == s.fPaintingData->fStitchDataInit; 560e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 561e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 56236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void onComputeInvariantOutput(GrInvariantOutput* inout) const override { 563605dd0fbce9dbb2a0d3313e13e161f2bd54870d7egdaniel inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput); 5641a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel } 5651a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel 566ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco GrPerlinNoiseEffect(SkPerlinNoiseShader::Type type, 567e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com int numOctaves, bool stitchTiles, 568ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkPerlinNoiseShader::PaintingData* paintingData, 569e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com GrTexture* permutationsTexture, GrTexture* noiseTexture, 570e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const SkMatrix& matrix, uint8_t alpha) 571f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco : fType(type) 572f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco , fNumOctaves(numOctaves) 573f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco , fStitchTiles(stitchTiles) 574f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco , fAlpha(alpha) 5754775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com , fPermutationsAccess(permutationsTexture) 576e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com , fNoiseAccess(noiseTexture) 577ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco , fPaintingData(paintingData) { 578eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt this->initClassID<GrPerlinNoiseEffect>(); 579e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com this->addTextureAccess(&fPermutationsAccess); 580e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com this->addTextureAccess(&fNoiseAccess); 581ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco fCoordTransform.reset(kLocal_GrCoordSet, matrix); 582f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco this->addCoordTransform(&fCoordTransform); 583e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 584e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 585b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 586e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 587f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco SkPerlinNoiseShader::Type fType; 588f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco GrCoordTransform fCoordTransform; 589f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco int fNumOctaves; 590f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco bool fStitchTiles; 591f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco uint8_t fAlpha; 592e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com GrTextureAccess fPermutationsAccess; 593e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com GrTextureAccess fNoiseAccess; 594ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkPerlinNoiseShader::PaintingData *fPaintingData; 595e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 5964775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.comprivate: 597b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt typedef GrFragmentProcessor INHERITED; 598e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com}; 599e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 600e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com///////////////////////////////////////////////////////////////////// 601b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrPerlinNoiseEffect); 602e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 603b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrFragmentProcessor* GrPerlinNoiseEffect::TestCreate(SkRandom* random, 604b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrContext* context, 605b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrDrawTargetCaps&, 606b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrTexture**) { 607423ac13f351b22308d3b1d039ab4859540be0b9dsugoi@google.com int numOctaves = random->nextRangeU(2, 10); 608e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com bool stitchTiles = random->nextBool(); 609e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkScalar seed = SkIntToScalar(random->nextU()); 610e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkISize tileSize = SkISize::Make(random->nextRangeU(4, 4096), random->nextRangeU(4, 4096)); 6114b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org SkScalar baseFrequencyX = random->nextRangeScalar(0.01f, 6124b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org 0.99f); 6134b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org SkScalar baseFrequencyY = random->nextRangeScalar(0.01f, 6144b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org 0.99f); 615e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 616e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkShader* shader = random->nextBool() ? 617e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkPerlinNoiseShader::CreateFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves, seed, 618e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com stitchTiles ? &tileSize : NULL) : 6199fbbcca1c958e6df2cff24d3ccdb7ebd89b8486bcommit-bot@chromium.org SkPerlinNoiseShader::CreateTurbulence(baseFrequencyX, baseFrequencyY, numOctaves, seed, 620e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com stitchTiles ? &tileSize : NULL); 621e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 622e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkPaint paint; 62383d081ae1d731b5039e99823620f5e287542ee39bsalomon GrColor paintColor; 624b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrFragmentProcessor* effect; 6255531d51ce7426bdae7563547326fcf0bf926a083joshualitt SkAssertResult(shader->asFragmentProcessor(context, paint, 6264eaf9cef5a76098f78efac30beb966ac833d32c2joshualitt GrTest::TestMatrix(random), NULL, 6275531d51ce7426bdae7563547326fcf0bf926a083joshualitt &paintColor, &effect)); 628e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 629e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkDELETE(shader); 630e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 631e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com return effect; 632e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 6334775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com 634eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualittGrGLPerlinNoise::GrGLPerlinNoise(const GrProcessor& processor) 635eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt : fType(processor.cast<GrPerlinNoiseEffect>().type()) 636b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt , fStitchTiles(processor.cast<GrPerlinNoiseEffect>().stitchTiles()) 637b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt , fNumOctaves(processor.cast<GrPerlinNoiseEffect>().numOctaves()) { 6384775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com} 6394775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com 6401598899975ecc85b003a59740b588d1ddbcedb09joshualittvoid GrGLPerlinNoise::emitCode(GrGLFPBuilder* builder, 641b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrFragmentProcessor&, 642e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* outputColor, 643e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* inputColor, 64477af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com const TransformedCoordsArray& coords, 645e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const TextureSamplerArray& samplers) { 646e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com sk_ignore_unused_variable(inputColor); 647e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 64829bee0fe657fabf7c396502b69c9167fba13eaaaegdaniel GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); 64930ba436f04e61d4505fb854d5fc56079636e0788joshualitt SkString vCoords = fsBuilder->ensureFSCoords2D(coords, 0); 650e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 65130ba436f04e61d4505fb854d5fc56079636e0788joshualitt fBaseFrequencyUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 652422f56f6e51c2f6a6ab425573b4d790f0157f883bsalomon kVec2f_GrSLType, kDefault_GrSLPrecision, 653422f56f6e51c2f6a6ab425573b4d790f0157f883bsalomon "baseFrequency"); 654e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* baseFrequencyUni = builder->getUniformCStr(fBaseFrequencyUni); 65530ba436f04e61d4505fb854d5fc56079636e0788joshualitt fAlphaUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 656422f56f6e51c2f6a6ab425573b4d790f0157f883bsalomon kFloat_GrSLType, kDefault_GrSLPrecision, 657422f56f6e51c2f6a6ab425573b4d790f0157f883bsalomon "alpha"); 658e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* alphaUni = builder->getUniformCStr(fAlphaUni); 659e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 660e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* stitchDataUni = NULL; 661e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com if (fStitchTiles) { 66230ba436f04e61d4505fb854d5fc56079636e0788joshualitt fStitchDataUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 663422f56f6e51c2f6a6ab425573b4d790f0157f883bsalomon kVec2f_GrSLType, kDefault_GrSLPrecision, 664422f56f6e51c2f6a6ab425573b4d790f0157f883bsalomon "stitchData"); 665e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com stitchDataUni = builder->getUniformCStr(fStitchDataUni); 666e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 667e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 668d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8 669d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com const char* chanCoordR = "0.125"; 670d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com const char* chanCoordG = "0.375"; 671d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com const char* chanCoordB = "0.625"; 672d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com const char* chanCoordA = "0.875"; 673d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com const char* chanCoord = "chanCoord"; 674e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* stitchData = "stitchData"; 675e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* ratio = "ratio"; 676e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* noiseVec = "noiseVec"; 677e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* noiseSmooth = "noiseSmooth"; 678ce6a354e121915c2925e545e7df2929492d69d50senorblanco const char* floorVal = "floorVal"; 679e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* fractVal = "fractVal"; 680e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* uv = "uv"; 681e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* ab = "ab"; 682e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* latticeIdx = "latticeIdx"; 683ce6a354e121915c2925e545e7df2929492d69d50senorblanco const char* bcoords = "bcoords"; 684e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* lattice = "lattice"; 685e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* inc8bit = "0.00390625"; // 1.0 / 256.0 686e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a 687e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // [-1,1] vector and perform a dot product between that vector and the provided vector. 688e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const char* dotLattice = "dot(((%s.ga + %s.rb * vec2(%s)) * vec2(2.0) - vec2(1.0)), %s);"; 689e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 690d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com // Add noise function 691d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com static const GrGLShaderVar gPerlinNoiseArgs[] = { 692d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com GrGLShaderVar(chanCoord, kFloat_GrSLType), 6939839320ae17ab1c2182dc144db5ba94caa1bde56commit-bot@chromium.org GrGLShaderVar(noiseVec, kVec2f_GrSLType) 694d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com }; 695e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 696d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com static const GrGLShaderVar gPerlinNoiseStitchArgs[] = { 697d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com GrGLShaderVar(chanCoord, kFloat_GrSLType), 6989839320ae17ab1c2182dc144db5ba94caa1bde56commit-bot@chromium.org GrGLShaderVar(noiseVec, kVec2f_GrSLType), 6999839320ae17ab1c2182dc144db5ba94caa1bde56commit-bot@chromium.org GrGLShaderVar(stitchData, kVec2f_GrSLType) 700d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com }; 701e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 702d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com SkString noiseCode; 703e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 704ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseCode.appendf("\tvec4 %s;\n", floorVal); 705ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec); 706ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal); 707ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec); 708e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 709e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // smooth curve : t * t * (3 - 2 * t) 710ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);", 711ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseSmooth, fractVal, fractVal, fractVal); 712e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 713e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Adjust frequencies if we're stitching tiles 714e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com if (fStitchTiles) { 7159839320ae17ab1c2182dc144db5ba94caa1bde56commit-bot@chromium.org noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }", 716ce6a354e121915c2925e545e7df2929492d69d50senorblanco floorVal, stitchData, floorVal, stitchData); 7179839320ae17ab1c2182dc144db5ba94caa1bde56commit-bot@chromium.org noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }", 718ce6a354e121915c2925e545e7df2929492d69d50senorblanco floorVal, stitchData, floorVal, stitchData); 719ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }", 720ce6a354e121915c2925e545e7df2929492d69d50senorblanco floorVal, stitchData, floorVal, stitchData); 721ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }", 722ce6a354e121915c2925e545e7df2929492d69d50senorblanco floorVal, stitchData, floorVal, stitchData); 723e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 724e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 725e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Get texture coordinates and normalize 726ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / vec4(256.0));\n", 727ce6a354e121915c2925e545e7df2929492d69d50senorblanco floorVal, floorVal); 728e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 729e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Get permutation for x 730e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com { 731e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkString xCoords(""); 732ce6a354e121915c2925e545e7df2929492d69d50senorblanco xCoords.appendf("vec2(%s.x, 0.5)", floorVal); 733e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 734d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx); 73530ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType); 736d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.append(".r;"); 737e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 738e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 739e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Get permutation for x + 1 740e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com { 741e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkString xCoords(""); 742ce6a354e121915c2925e545e7df2929492d69d50senorblanco xCoords.appendf("vec2(%s.z, 0.5)", floorVal); 743e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 744d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf("\n\t%s.y = ", latticeIdx); 74530ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType); 746d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.append(".r;"); 747e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 748e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 749344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org#if defined(SK_BUILD_FOR_ANDROID) 750344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org // Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3). 751344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org // The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit 752344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org // value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725 753344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org // (or 0.484368 here). The following rounding operation prevents these precision issues from 754344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org // affecting the result of the noise by making sure that we only have multiples of 1/255. 755344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org // (Note that 1/255 is about 0.003921569, which is the value used here). 756344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org noiseCode.appendf("\n\t%s = floor(%s * vec2(255.0) + vec2(0.5)) * vec2(0.003921569);", 757344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org latticeIdx, latticeIdx); 758344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org#endif 759344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org 760e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Get (x,y) coordinates with the permutated x 761ce6a354e121915c2925e545e7df2929492d69d50senorblanco noiseCode.appendf("\n\tvec4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal); 762e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 763d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf("\n\n\tvec2 %s;", uv); 764e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Compute u, at offset (0,0) 765e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com { 766e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkString latticeCoords(""); 767ce6a354e121915c2925e545e7df2929492d69d50senorblanco latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord); 768d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf("\n\tvec4 %s = ", lattice); 76930ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), 770d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com kVec2f_GrSLType); 771d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf(".bgra;\n\t%s.x = ", uv); 772d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); 773e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 774e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 775d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal); 776e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Compute v, at offset (-1,0) 777e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com { 778e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkString latticeCoords(""); 779ce6a354e121915c2925e545e7df2929492d69d50senorblanco latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord); 780344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org noiseCode.append("\n\tlattice = "); 78130ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), 782d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com kVec2f_GrSLType); 783d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf(".bgra;\n\t%s.y = ", uv); 784d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); 785e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 786e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 787e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Compute 'a' as a linear interpolation of 'u' and 'v' 788d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf("\n\tvec2 %s;", ab); 789d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth); 790e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 791d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal); 792e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Compute v, at offset (-1,-1) 793e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com { 794e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkString latticeCoords(""); 795ce6a354e121915c2925e545e7df2929492d69d50senorblanco latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord); 796344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org noiseCode.append("\n\tlattice = "); 79730ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), 798d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com kVec2f_GrSLType); 799d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf(".bgra;\n\t%s.y = ", uv); 800d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); 801e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 802e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 803d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf("\n\t%s.x += 1.0;", fractVal); 804e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Compute u, at offset (0,-1) 805e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com { 806e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkString latticeCoords(""); 807ce6a354e121915c2925e545e7df2929492d69d50senorblanco latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord); 808344cf45a40c7de3c4664f8a048d4017af88adfeecommit-bot@chromium.org noiseCode.append("\n\tlattice = "); 80930ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), 810d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com kVec2f_GrSLType); 811d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf(".bgra;\n\t%s.x = ", uv); 812d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); 813e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 814e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 815e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Compute 'b' as a linear interpolation of 'u' and 'v' 816d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth); 817e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Compute the noise as a linear interpolation of 'a' and 'b' 818d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth); 819d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com 820d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com SkString noiseFuncName; 821d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com if (fStitchTiles) { 82230ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->emitFunction(kFloat_GrSLType, 82374a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs), 82474a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName); 825d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com } else { 82630ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->emitFunction(kFloat_GrSLType, 82774a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs), 82874a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName); 829d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com } 830e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 831d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com // There are rounding errors if the floor operation is not performed here 83230ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;", 833ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco noiseVec, vCoords.c_str(), baseFrequencyUni); 834e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 835d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com // Clear the color accumulator 83630ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", outputColor); 837e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 838e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com if (fStitchTiles) { 839d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com // Set up TurbulenceInitial stitch values. 84030ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\tvec2 %s = %s;", stitchData, stitchDataUni); 841e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 842e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 84330ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\tfloat %s = 1.0;", ratio); 844d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com 845d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com // Loop over all octaves 84630ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\tfor (int octave = 0; octave < %d; ++octave) {", fNumOctaves); 847d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com 84830ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\t\t%s += ", outputColor); 849d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com if (fType != SkPerlinNoiseShader::kFractalNoise_Type) { 85030ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("abs("); 851d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com } 852d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com if (fStitchTiles) { 85330ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf( 854d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s)," 855d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))", 856d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData, 857d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData, 858d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData, 859d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData); 860d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com } else { 86130ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf( 862d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s)," 863d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))", 864d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseFuncName.c_str(), chanCoordR, noiseVec, 865d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseFuncName.c_str(), chanCoordG, noiseVec, 866d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseFuncName.c_str(), chanCoordB, noiseVec, 867d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com noiseFuncName.c_str(), chanCoordA, noiseVec); 868d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com } 869d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com if (fType != SkPerlinNoiseShader::kFractalNoise_Type) { 87030ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf(")"); // end of "abs(" 871d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com } 87230ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf(" * %s;", ratio); 873d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com 87430ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec); 87530ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio); 876d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com 877d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com if (fStitchTiles) { 87830ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData); 879d537af50fcd013aa69fddc24afb1b997408ec762sugoi@google.com } 88030ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves 881e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 882e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com if (fType == SkPerlinNoiseShader::kFractalNoise_Type) { 883e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2 884e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // by fractalNoise and (turbulenceFunctionResult) by turbulence. 88530ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);", outputColor, outputColor); 886e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 887e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 88830ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\t%s.a *= %s;", outputColor, alphaUni); 889e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 890e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Clamp values 89130ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", outputColor, outputColor); 892e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 893e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Pre-multiply the result 89430ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n", 895e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com outputColor, outputColor, outputColor, outputColor); 896e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 897e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 898cfc18867d982119d9dc2888bf09f1093012daaddjvanverthvoid GrGLPerlinNoise::GenKey(const GrProcessor& processor, const GrGLSLCaps&, 899b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrProcessorKeyBuilder* b) { 900b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrPerlinNoiseEffect& turbulence = processor.cast<GrPerlinNoiseEffect>(); 901e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 90263e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon uint32_t key = turbulence.numOctaves(); 903e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 904e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com key = key << 3; // Make room for next 3 bits 905e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 906e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com switch (turbulence.type()) { 907e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com case SkPerlinNoiseShader::kFractalNoise_Type: 908e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com key |= 0x1; 909e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com break; 910e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com case SkPerlinNoiseShader::kTurbulence_Type: 911e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com key |= 0x2; 912e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com break; 913e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com default: 914e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // leave key at 0 915e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com break; 916e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 917e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 918e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com if (turbulence.stitchTiles()) { 919e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com key |= 0x4; // Flip the 3rd bit if tile stitching is on 920e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 921e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 92263e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon b->add32(key); 923e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 924e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 925b0a8a377f832c59cee939ad721e1f87d378b7142joshualittvoid GrGLPerlinNoise::setData(const GrGLProgramDataManager& pdman, const GrProcessor& processor) { 926b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt INHERITED::setData(pdman, processor); 927f3b50276a4ad71c9e8ba13d752a5db0c073cae2csenorblanco 928b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrPerlinNoiseEffect& turbulence = processor.cast<GrPerlinNoiseEffect>(); 929e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 930e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com const SkVector& baseFrequency = turbulence.baseFrequency(); 9317510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY); 93280ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed pdman.set1f(fAlphaUni, SkIntToScalar(turbulence.alpha()) / 255); 933e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 9344775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com if (turbulence.stitchTiles()) { 9354775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com const SkPerlinNoiseShader::StitchData& stitchData = turbulence.stitchData(); 9367510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth), 9379839320ae17ab1c2182dc144db5ba94caa1bde56commit-bot@chromium.org SkIntToScalar(stitchData.fHeight)); 9384775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com } 9394775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com} 9404775cba7b37e24e8480bd2d96e297fd0828fb5c3sugoi@google.com 941e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com///////////////////////////////////////////////////////////////////// 942e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 943b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool SkPerlinNoiseShader::asFragmentProcessor(GrContext* context, const SkPaint& paint, 9445531d51ce7426bdae7563547326fcf0bf926a083joshualitt const SkMatrix& viewM, 945b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const SkMatrix* externalLocalMatrix, 946b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrColor* paintColor, GrFragmentProcessor** fp) const { 94749f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(context); 9483f3b3d003527861dc0bd89733857576408906431mtklein 94983d081ae1d731b5039e99823620f5e287542ee39bsalomon *paintColor = SkColor2GrColorJustAlpha(paint.getColor()); 950ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco 95196fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org SkMatrix localMatrix = this->getLocalMatrix(); 95296fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org if (externalLocalMatrix) { 95396fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org localMatrix.preConcat(*externalLocalMatrix); 95496fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org } 95596fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org 9565531d51ce7426bdae7563547326fcf0bf926a083joshualitt SkMatrix matrix = viewM; 957ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco matrix.preConcat(localMatrix); 958ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco 959c2a0ea6418988d4bcc0719f99b1a110cecd08679commit-bot@chromium.org if (0 == fNumOctaves) { 960c2a0ea6418988d4bcc0719f99b1a110cecd08679commit-bot@chromium.org if (kFractalNoise_Type == fType) { 961ea8b55db889b19786008b7c613d238e7202485e5bsalomon uint32_t alpha = paint.getAlpha() >> 1; 962ea8b55db889b19786008b7c613d238e7202485e5bsalomon uint32_t rgb = alpha >> 1; 963ea8b55db889b19786008b7c613d238e7202485e5bsalomon *paintColor = GrColorPackRGBA(rgb, rgb, rgb, alpha); 964ea8b55db889b19786008b7c613d238e7202485e5bsalomon } else { 965ea8b55db889b19786008b7c613d238e7202485e5bsalomon *paintColor = 0; 966cff10b21a9934afc540d121b493b204335829589reed } 9679de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return true; 968c2a0ea6418988d4bcc0719f99b1a110cecd08679commit-bot@chromium.org } 969c2a0ea6418988d4bcc0719f99b1a110cecd08679commit-bot@chromium.org 970e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com // Either we don't stitch tiles, either we have a valid tile size 971e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkASSERT(!fStitchTiles || !fTileSize.isEmpty()); 972e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 973b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkPerlinNoiseShader::PaintingData* paintingData = 974b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkNEW_ARGS(PaintingData, (fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY, matrix)); 975bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon SkAutoTUnref<GrTexture> permutationsTexture( 976bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon GrRefCachedBitmapTexture(context, paintingData->getPermutationsBitmap(), NULL)); 977bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon SkAutoTUnref<GrTexture> noiseTexture( 978bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon GrRefCachedBitmapTexture(context, paintingData->getNoiseBitmap(), NULL)); 979ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco 9805531d51ce7426bdae7563547326fcf0bf926a083joshualitt SkMatrix m = viewM; 981ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1); 982ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1); 98349f085dddff10473b6ebf832a974288300224e60bsalomon if ((permutationsTexture) && (noiseTexture)) { 984b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt *fp = GrPerlinNoiseEffect::Create(fType, 985b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt fNumOctaves, 986b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt fStitchTiles, 987b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt paintingData, 988b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt permutationsTexture, noiseTexture, 989b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt m, paint.getAlpha()); 990ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco } else { 991ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco SkDELETE(paintingData); 992b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt *fp = NULL; 993ca6a7c29452e13cf63bb4e225972065cbfe6e265senorblanco } 9949de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return true; 995e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 996e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 997e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#else 998e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 9995531d51ce7426bdae7563547326fcf0bf926a083joshualittbool SkPerlinNoiseShader::asFragmentProcessor(GrContext*, const SkPaint&, const SkMatrix&, 10005531d51ce7426bdae7563547326fcf0bf926a083joshualitt const SkMatrix*, GrColor*, 1001b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrFragmentProcessor**) const { 1002e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com SkDEBUGFAIL("Should not call in GPU-less build"); 10039de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return false; 1004e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 1005e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 1006e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#endif 1007e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 10080f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING 1009e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.comvoid SkPerlinNoiseShader::toString(SkString* str) const { 1010e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append("SkPerlinNoiseShader: ("); 1011e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 1012e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append("type: "); 1013e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com switch (fType) { 1014e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com case kFractalNoise_Type: 1015e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append("\"fractal noise\""); 1016e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com break; 1017e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com case kTurbulence_Type: 1018e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append("\"turbulence\""); 1019e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com break; 1020e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com default: 1021e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append("\"unknown\""); 1022e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com break; 1023e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com } 1024e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append(" base frequency: ("); 1025e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->appendScalar(fBaseFrequencyX); 1026e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append(", "); 1027e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->appendScalar(fBaseFrequencyY); 1028e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append(") number of octaves: "); 1029e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->appendS32(fNumOctaves); 1030e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append(" seed: "); 1031e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->appendScalar(fSeed); 1032e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append(" stitch tiles: "); 1033e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append(fStitchTiles ? "true " : "false "); 1034e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 1035e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com this->INHERITED::toString(str); 1036e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com 1037e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com str->append(")"); 1038e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com} 1039e3b4c5097a6fd9b6c09d2ffbc3db170a287fdd99sugoi@google.com#endif 1040