gfx/skia/trunk/src/effects/SkPerlinNoiseShader.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /*
     2  * Copyright 2013 Google Inc.
     3  *
     4  * Use of this source code is governed by a BSD-style license that can be
     5  * found in the LICENSE file.
     6  */
     8 #include "SkDither.h"
     9 #include "SkPerlinNoiseShader.h"
    10 #include "SkColorFilter.h"
    11 #include "SkReadBuffer.h"
    12 #include "SkWriteBuffer.h"
    13 #include "SkShader.h"
    14 #include "SkUnPreMultiply.h"
    15 #include "SkString.h"
    17 #if SK_SUPPORT_GPU
    18 #include "GrContext.h"
    19 #include "GrCoordTransform.h"
    20 #include "gl/GrGLEffect.h"
    21 #include "GrTBackendEffectFactory.h"
    22 #include "SkGr.h"
    23 #endif
    25 static const int kBlockSize = 256;
    26 static const int kBlockMask = kBlockSize - 1;
    27 static const int kPerlinNoise = 4096;
    28 static const int kRandMaximum = SK_MaxS32; // 2**31 - 1
    30 namespace {
    32 // noiseValue is the color component's value (or color)
    33 // limitValue is the maximum perlin noise array index value allowed
    34 // newValue is the current noise dimension (either width or height)
    35 inline int checkNoise(int noiseValue, int limitValue, int newValue) {
    36     // If the noise value would bring us out of bounds of the current noise array while we are
    37     // stiching noise tiles together, wrap the noise around the current dimension of the noise to
    38     // stay within the array bounds in a continuous fashion (so that tiling lines are not visible)
    39     if (noiseValue >= limitValue) {
    40         noiseValue -= newValue;
    41     }
    42     if (noiseValue >= limitValue - 1) {
    43         noiseValue -= newValue - 1;
    44     }
    45     return noiseValue;
    46 }
    48 inline SkScalar smoothCurve(SkScalar t) {
    49     static const SkScalar SK_Scalar3 = 3.0f;
    51     // returns t * t * (3 - 2 * t)
    52     return SkScalarMul(SkScalarSquare(t), SK_Scalar3 - 2 * t);
    53 }
    55 bool perlin_noise_type_is_valid(SkPerlinNoiseShader::Type type) {
    56     return (SkPerlinNoiseShader::kFractalNoise_Type == type) ||
    57            (SkPerlinNoiseShader::kTurbulence_Type == type);
    58 }
    60 } // end namespace
    62 struct SkPerlinNoiseShader::StitchData {
    63     StitchData()
    64       : fWidth(0)
    65       , fWrapX(0)
    66       , fHeight(0)
    67       , fWrapY(0)
    68     {}
    70     bool operator==(const StitchData& other) const {
    71         return fWidth == other.fWidth &&
    72                fWrapX == other.fWrapX &&
    73                fHeight == other.fHeight &&
    74                fWrapY == other.fWrapY;
    75     }
    77     int fWidth; // How much to subtract to wrap for stitching.
    78     int fWrapX; // Minimum value to wrap.
    79     int fHeight;
    80     int fWrapY;
    81 };
    83 struct SkPerlinNoiseShader::PaintingData {
    84     PaintingData(const SkISize& tileSize, SkScalar seed,
    85                  SkScalar baseFrequencyX, SkScalar baseFrequencyY)
    86       : fTileSize(tileSize)
    87       , fBaseFrequency(SkPoint::Make(baseFrequencyX, baseFrequencyY))
    88     {
    89         this->init(seed);
    90         if (!fTileSize.isEmpty()) {
    91             this->stitch();
    92         }
    94 #if SK_SUPPORT_GPU && !defined(SK_USE_SIMPLEX_NOISE)
    95         fPermutationsBitmap.setConfig(SkImageInfo::MakeA8(kBlockSize, 1));
    96         fPermutationsBitmap.setPixels(fLatticeSelector);
    98         fNoiseBitmap.setConfig(SkImageInfo::MakeN32Premul(kBlockSize, 4));
    99         fNoiseBitmap.setPixels(fNoise[0][0]);
   100 #endif
   101     }
   103     int         fSeed;
   104     uint8_t     fLatticeSelector[kBlockSize];
   105     uint16_t    fNoise[4][kBlockSize][2];
   106     SkPoint     fGradient[4][kBlockSize];
   107     SkISize     fTileSize;
   108     SkVector    fBaseFrequency;
   109     StitchData  fStitchDataInit;
   111 private:
   113 #if SK_SUPPORT_GPU && !defined(SK_USE_SIMPLEX_NOISE)
   114     SkBitmap   fPermutationsBitmap;
   115     SkBitmap   fNoiseBitmap;
   116 #endif
   118     inline int random()  {
   119         static const int gRandAmplitude = 16807; // 7**5; primitive root of m
   120         static const int gRandQ = 127773; // m / a
   121         static const int gRandR = 2836; // m % a
   123         int result = gRandAmplitude * (fSeed % gRandQ) - gRandR * (fSeed / gRandQ);
   124         if (result <= 0)
   125             result += kRandMaximum;
   126         fSeed = result;
   127         return result;
   128     }
   130     // Only called once. Could be part of the constructor.
   131     void init(SkScalar seed)
   132     {
   133         static const SkScalar gInvBlockSizef = SkScalarInvert(SkIntToScalar(kBlockSize));
   135         // According to the SVG spec, we must truncate (not round) the seed value.
   136         fSeed = SkScalarTruncToInt(seed);
   137         // The seed value clamp to the range [1, kRandMaximum - 1].
   138         if (fSeed <= 0) {
   139             fSeed = -(fSeed % (kRandMaximum - 1)) + 1;
   140         }
   141         if (fSeed > kRandMaximum - 1) {
   142             fSeed = kRandMaximum - 1;
   143         }
   144         for (int channel = 0; channel < 4; ++channel) {
   145             for (int i = 0; i < kBlockSize; ++i) {
   146                 fLatticeSelector[i] = i;
   147                 fNoise[channel][i][0] = (random() % (2 * kBlockSize));
   148                 fNoise[channel][i][1] = (random() % (2 * kBlockSize));
   149             }
   150         }
   151         for (int i = kBlockSize - 1; i > 0; --i) {
   152             int k = fLatticeSelector[i];
   153             int j = random() % kBlockSize;
   154             SkASSERT(j >= 0);
   155             SkASSERT(j < kBlockSize);
   156             fLatticeSelector[i] = fLatticeSelector[j];
   157             fLatticeSelector[j] = k;
   158         }
   160         // Perform the permutations now
   161         {
   162             // Copy noise data
   163             uint16_t noise[4][kBlockSize][2];
   164             for (int i = 0; i < kBlockSize; ++i) {
   165                 for (int channel = 0; channel < 4; ++channel) {
   166                     for (int j = 0; j < 2; ++j) {
   167                         noise[channel][i][j] = fNoise[channel][i][j];
   168                     }
   169                 }
   170             }
   171             // Do permutations on noise data
   172             for (int i = 0; i < kBlockSize; ++i) {
   173                 for (int channel = 0; channel < 4; ++channel) {
   174                     for (int j = 0; j < 2; ++j) {
   175                         fNoise[channel][i][j] = noise[channel][fLatticeSelector[i]][j];
   176                     }
   177                 }
   178             }
   179         }
   181         // Half of the largest possible value for 16 bit unsigned int
   182         static const SkScalar gHalfMax16bits = 32767.5f;
   184         // Compute gradients from permutated noise data
   185         for (int channel = 0; channel < 4; ++channel) {
   186             for (int i = 0; i < kBlockSize; ++i) {
   187                 fGradient[channel][i] = SkPoint::Make(
   188                     SkScalarMul(SkIntToScalar(fNoise[channel][i][0] - kBlockSize),
   189                                 gInvBlockSizef),
   190                     SkScalarMul(SkIntToScalar(fNoise[channel][i][1] - kBlockSize),
   191                                 gInvBlockSizef));
   192                 fGradient[channel][i].normalize();
   193                 // Put the normalized gradient back into the noise data
   194                 fNoise[channel][i][0] = SkScalarRoundToInt(SkScalarMul(
   195                     fGradient[channel][i].fX + SK_Scalar1, gHalfMax16bits));
   196                 fNoise[channel][i][1] = SkScalarRoundToInt(SkScalarMul(
   197                     fGradient[channel][i].fY + SK_Scalar1, gHalfMax16bits));
   198             }
   199         }
   200     }
   202     // Only called once. Could be part of the constructor.
   203     void stitch() {
   204         SkScalar tileWidth  = SkIntToScalar(fTileSize.width());
   205         SkScalar tileHeight = SkIntToScalar(fTileSize.height());
   206         SkASSERT(tileWidth > 0 && tileHeight > 0);
   207         // When stitching tiled turbulence, the frequencies must be adjusted
   208         // so that the tile borders will be continuous.
   209         if (fBaseFrequency.fX) {
   210             SkScalar lowFrequencx =
   211                 SkScalarFloorToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
   212             SkScalar highFrequencx =
   213                 SkScalarCeilToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
   214             // BaseFrequency should be non-negative according to the standard.
   215             if (SkScalarDiv(fBaseFrequency.fX, lowFrequencx) <
   216                 SkScalarDiv(highFrequencx, fBaseFrequency.fX)) {
   217                 fBaseFrequency.fX = lowFrequencx;
   218             } else {
   219                 fBaseFrequency.fX = highFrequencx;
   220             }
   221         }
   222         if (fBaseFrequency.fY) {
   223             SkScalar lowFrequency =
   224                 SkScalarFloorToScalar(tileHeight * fBaseFrequency.fY) / tileHeight;
   225             SkScalar highFrequency =
   226                 SkScalarCeilToScalar(tileHeight * fBaseFrequency.fY) / tileHeight;
   227             if (SkScalarDiv(fBaseFrequency.fY, lowFrequency) <
   228                 SkScalarDiv(highFrequency, fBaseFrequency.fY)) {
   229                 fBaseFrequency.fY = lowFrequency;
   230             } else {
   231                 fBaseFrequency.fY = highFrequency;
   232             }
   233         }
   234         // Set up TurbulenceInitial stitch values.
   235         fStitchDataInit.fWidth  =
   236             SkScalarRoundToInt(tileWidth * fBaseFrequency.fX);
   237         fStitchDataInit.fWrapX  = kPerlinNoise + fStitchDataInit.fWidth;
   238         fStitchDataInit.fHeight =
   239             SkScalarRoundToInt(tileHeight * fBaseFrequency.fY);
   240         fStitchDataInit.fWrapY  = kPerlinNoise + fStitchDataInit.fHeight;
   241     }
   243 public:
   245 #if SK_SUPPORT_GPU && !defined(SK_USE_SIMPLEX_NOISE)
   246     const SkBitmap& getPermutationsBitmap() const { return fPermutationsBitmap; }
   248     const SkBitmap& getNoiseBitmap() const { return fNoiseBitmap; }
   249 #endif
   250 };
   252 SkShader* SkPerlinNoiseShader::CreateFractalNoise(SkScalar baseFrequencyX, SkScalar baseFrequencyY,
   253                                                   int numOctaves, SkScalar seed,
   254                                                   const SkISize* tileSize) {
   255     return SkNEW_ARGS(SkPerlinNoiseShader, (kFractalNoise_Type, baseFrequencyX, baseFrequencyY,
   256                                             numOctaves, seed, tileSize));
   257 }
   259 SkShader* SkPerlinNoiseShader::CreateTubulence(SkScalar baseFrequencyX, SkScalar baseFrequencyY,
   260                                               int numOctaves, SkScalar seed,
   261                                               const SkISize* tileSize) {
   262     return SkNEW_ARGS(SkPerlinNoiseShader, (kTurbulence_Type, baseFrequencyX, baseFrequencyY,
   263                                             numOctaves, seed, tileSize));
   264 }
   266 SkPerlinNoiseShader::SkPerlinNoiseShader(SkPerlinNoiseShader::Type type,
   267                                          SkScalar baseFrequencyX,
   268                                          SkScalar baseFrequencyY,
   269                                          int numOctaves,
   270                                          SkScalar seed,
   271                                          const SkISize* tileSize)
   272   : fType(type)
   273   , fBaseFrequencyX(baseFrequencyX)
   274   , fBaseFrequencyY(baseFrequencyY)
   275   , fNumOctaves(numOctaves > 255 ? 255 : numOctaves/*[0,255] octaves allowed*/)
   276   , fSeed(seed)
   277   , fTileSize(NULL == tileSize ? SkISize::Make(0, 0) : *tileSize)
   278   , fStitchTiles(!fTileSize.isEmpty())
   279 {
   280     SkASSERT(numOctaves >= 0 && numOctaves < 256);
   281     fMatrix.reset();
   282     fPaintingData = SkNEW_ARGS(PaintingData, (fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY));
   283 }
   285 SkPerlinNoiseShader::SkPerlinNoiseShader(SkReadBuffer& buffer)
   286     : INHERITED(buffer)
   287 {
   288     fType           = (SkPerlinNoiseShader::Type) buffer.readInt();
   289     fBaseFrequencyX = buffer.readScalar();
   290     fBaseFrequencyY = buffer.readScalar();
   291     fNumOctaves     = buffer.readInt();
   292     fSeed           = buffer.readScalar();
   293     fStitchTiles    = buffer.readBool();
   294     fTileSize.fWidth  = buffer.readInt();
   295     fTileSize.fHeight = buffer.readInt();
   296     fMatrix.reset();
   297     fPaintingData = SkNEW_ARGS(PaintingData, (fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY));
   298     buffer.validate(perlin_noise_type_is_valid(fType) &&
   299                     (fNumOctaves >= 0) && (fNumOctaves <= 255) &&
   300                     (fStitchTiles != fTileSize.isEmpty()));
   301 }
   303 SkPerlinNoiseShader::~SkPerlinNoiseShader() {
   304     // Safety, should have been done in endContext()
   305     SkDELETE(fPaintingData);
   306 }
   308 void SkPerlinNoiseShader::flatten(SkWriteBuffer& buffer) const {
   309     this->INHERITED::flatten(buffer);
   310     buffer.writeInt((int) fType);
   311     buffer.writeScalar(fBaseFrequencyX);
   312     buffer.writeScalar(fBaseFrequencyY);
   313     buffer.writeInt(fNumOctaves);
   314     buffer.writeScalar(fSeed);
   315     buffer.writeBool(fStitchTiles);
   316     buffer.writeInt(fTileSize.fWidth);
   317     buffer.writeInt(fTileSize.fHeight);
   318 }
   320 SkScalar SkPerlinNoiseShader::noise2D(int channel, const PaintingData& paintingData,
   321                                       const StitchData& stitchData,
   322                                       const SkPoint& noiseVector) const {
   323     struct Noise {
   324         int noisePositionIntegerValue;
   325         SkScalar noisePositionFractionValue;
   326         Noise(SkScalar component)
   327         {
   328             SkScalar position = component + kPerlinNoise;
   329             noisePositionIntegerValue = SkScalarFloorToInt(position);
   330             noisePositionFractionValue = position - SkIntToScalar(noisePositionIntegerValue);
   331         }
   332     };
   333     Noise noiseX(noiseVector.x());
   334     Noise noiseY(noiseVector.y());
   335     SkScalar u, v;
   336     // If stitching, adjust lattice points accordingly.
   337     if (fStitchTiles) {
   338         noiseX.noisePositionIntegerValue =
   339             checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
   340         noiseY.noisePositionIntegerValue =
   341             checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
   342     }
   343     noiseX.noisePositionIntegerValue &= kBlockMask;
   344     noiseY.noisePositionIntegerValue &= kBlockMask;
   345     int latticeIndex =
   346         paintingData.fLatticeSelector[noiseX.noisePositionIntegerValue] +
   347         noiseY.noisePositionIntegerValue;
   348     int nextLatticeIndex =
   349         paintingData.fLatticeSelector[(noiseX.noisePositionIntegerValue + 1) & kBlockMask] +
   350         noiseY.noisePositionIntegerValue;
   351     SkScalar sx = smoothCurve(noiseX.noisePositionFractionValue);
   352     SkScalar sy = smoothCurve(noiseY.noisePositionFractionValue);
   353     // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement
   354     SkPoint fractionValue = SkPoint::Make(noiseX.noisePositionFractionValue,
   355                                           noiseY.noisePositionFractionValue); // Offset (0,0)
   356     u = paintingData.fGradient[channel][latticeIndex & kBlockMask].dot(fractionValue);
   357     fractionValue.fX -= SK_Scalar1; // Offset (-1,0)
   358     v = paintingData.fGradient[channel][nextLatticeIndex & kBlockMask].dot(fractionValue);
   359     SkScalar a = SkScalarInterp(u, v, sx);
   360     fractionValue.fY -= SK_Scalar1; // Offset (-1,-1)
   361     v = paintingData.fGradient[channel][(nextLatticeIndex + 1) & kBlockMask].dot(fractionValue);
   362     fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1)
   363     u = paintingData.fGradient[channel][(latticeIndex + 1) & kBlockMask].dot(fractionValue);
   364     SkScalar b = SkScalarInterp(u, v, sx);
   365     return SkScalarInterp(a, b, sy);
   366 }
   368 SkScalar SkPerlinNoiseShader::calculateTurbulenceValueForPoint(int channel,
   369                                                                const PaintingData& paintingData,
   370                                                                StitchData& stitchData,
   371                                                                const SkPoint& point) const {
   372     if (fStitchTiles) {
   373         // Set up TurbulenceInitial stitch values.
   374         stitchData = paintingData.fStitchDataInit;
   375     }
   376     SkScalar turbulenceFunctionResult = 0;
   377     SkPoint noiseVector(SkPoint::Make(SkScalarMul(point.x(), paintingData.fBaseFrequency.fX),
   378                                       SkScalarMul(point.y(), paintingData.fBaseFrequency.fY)));
   379     SkScalar ratio = SK_Scalar1;
   380     for (int octave = 0; octave < fNumOctaves; ++octave) {
   381         SkScalar noise = noise2D(channel, paintingData, stitchData, noiseVector);
   382         turbulenceFunctionResult += SkScalarDiv(
   383             (fType == kFractalNoise_Type) ? noise : SkScalarAbs(noise), ratio);
   384         noiseVector.fX *= 2;
   385         noiseVector.fY *= 2;
   386         ratio *= 2;
   387         if (fStitchTiles) {
   388             // Update stitch values
   389             stitchData.fWidth  *= 2;
   390             stitchData.fWrapX   = stitchData.fWidth + kPerlinNoise;
   391             stitchData.fHeight *= 2;
   392             stitchData.fWrapY   = stitchData.fHeight + kPerlinNoise;
   393         }
   394     }
   396     // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
   397     // by fractalNoise and (turbulenceFunctionResult) by turbulence.
   398     if (fType == kFractalNoise_Type) {
   399         turbulenceFunctionResult =
   400             SkScalarMul(turbulenceFunctionResult, SK_ScalarHalf) + SK_ScalarHalf;
   401     }
   403     if (channel == 3) { // Scale alpha by paint value
   404         turbulenceFunctionResult = SkScalarMul(turbulenceFunctionResult,
   405             SkScalarDiv(SkIntToScalar(getPaintAlpha()), SkIntToScalar(255)));
   406     }
   408     // Clamp result
   409     return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1);
   410 }
   412 SkPMColor SkPerlinNoiseShader::shade(const SkPoint& point, StitchData& stitchData) const {
   413     SkMatrix matrix = fMatrix;
   414     matrix.postConcat(getLocalMatrix());
   415     SkMatrix invMatrix;
   416     if (!matrix.invert(&invMatrix)) {
   417         invMatrix.reset();
   418     } else {
   419         invMatrix.postConcat(invMatrix); // Square the matrix
   420     }
   421     // This (1,1) translation is due to WebKit's 1 based coordinates for the noise
   422     // (as opposed to 0 based, usually). The same adjustment is in the setData() function.
   423     matrix.postTranslate(SK_Scalar1, SK_Scalar1);
   424     SkPoint newPoint;
   425     matrix.mapPoints(&newPoint, &point, 1);
   426     invMatrix.mapPoints(&newPoint, &newPoint, 1);
   427     newPoint.fX = SkScalarRoundToScalar(newPoint.fX);
   428     newPoint.fY = SkScalarRoundToScalar(newPoint.fY);
   430     U8CPU rgba[4];
   431     for (int channel = 3; channel >= 0; --channel) {
   432         rgba[channel] = SkScalarFloorToInt(255 *
   433             calculateTurbulenceValueForPoint(channel, *fPaintingData, stitchData, newPoint));
   434     }
   435     return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]);
   436 }
   438 bool SkPerlinNoiseShader::setContext(const SkBitmap& device, const SkPaint& paint,
   439                                      const SkMatrix& matrix) {
   440     fMatrix = matrix;
   441     return INHERITED::setContext(device, paint, matrix);
   442 }
   444 void SkPerlinNoiseShader::shadeSpan(int x, int y, SkPMColor result[], int count) {
   445     SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
   446     StitchData stitchData;
   447     for (int i = 0; i < count; ++i) {
   448         result[i] = shade(point, stitchData);
   449         point.fX += SK_Scalar1;
   450     }
   451 }
   453 void SkPerlinNoiseShader::shadeSpan16(int x, int y, uint16_t result[], int count) {
   454     SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
   455     StitchData stitchData;
   456     DITHER_565_SCAN(y);
   457     for (int i = 0; i < count; ++i) {
   458         unsigned dither = DITHER_VALUE(x);
   459         result[i] = SkDitherRGB32To565(shade(point, stitchData), dither);
   460         DITHER_INC_X(x);
   461         point.fX += SK_Scalar1;
   462     }
   463 }
   465 /////////////////////////////////////////////////////////////////////
   467 #if SK_SUPPORT_GPU
   469 #include "GrTBackendEffectFactory.h"
   471 class GrGLNoise : public GrGLEffect {
   472 public:
   473     GrGLNoise(const GrBackendEffectFactory& factory,
   474               const GrDrawEffect& drawEffect);
   475     virtual ~GrGLNoise() {}
   477     static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
   479     virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
   481 protected:
   482     SkPerlinNoiseShader::Type           fType;
   483     bool                                fStitchTiles;
   484     int                                 fNumOctaves;
   485     GrGLUniformManager::UniformHandle   fBaseFrequencyUni;
   486     GrGLUniformManager::UniformHandle   fAlphaUni;
   487     GrGLUniformManager::UniformHandle   fInvMatrixUni;
   489 private:
   490     typedef GrGLEffect INHERITED;
   491 };
   493 class GrGLPerlinNoise : public GrGLNoise {
   494 public:
   495     GrGLPerlinNoise(const GrBackendEffectFactory& factory,
   496                     const GrDrawEffect& drawEffect)
   497       : GrGLNoise(factory, drawEffect) {}
   498     virtual ~GrGLPerlinNoise() {}
   500     virtual void emitCode(GrGLShaderBuilder*,
   501                           const GrDrawEffect&,
   502                           EffectKey,
   503                           const char* outputColor,
   504                           const char* inputColor,
   505                           const TransformedCoordsArray&,
   506                           const TextureSamplerArray&) SK_OVERRIDE;
   508     virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
   510 private:
   511     GrGLUniformManager::UniformHandle fStitchDataUni;
   513     typedef GrGLNoise INHERITED;
   514 };
   516 class GrGLSimplexNoise : public GrGLNoise {
   517     // Note : This is for reference only. GrGLPerlinNoise is used for processing.
   518 public:
   519     GrGLSimplexNoise(const GrBackendEffectFactory& factory,
   520                      const GrDrawEffect& drawEffect)
   521       : GrGLNoise(factory, drawEffect) {}
   523     virtual ~GrGLSimplexNoise() {}
   525     virtual void emitCode(GrGLShaderBuilder*,
   526                           const GrDrawEffect&,
   527                           EffectKey,
   528                           const char* outputColor,
   529                           const char* inputColor,
   530                           const TransformedCoordsArray&,
   531                           const TextureSamplerArray&) SK_OVERRIDE;
   533     virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
   535 private:
   536     GrGLUniformManager::UniformHandle fSeedUni;
   538     typedef GrGLNoise INHERITED;
   539 };
   541 /////////////////////////////////////////////////////////////////////
   543 class GrNoiseEffect : public GrEffect {
   544 public:
   545     virtual ~GrNoiseEffect() { }
   547     SkPerlinNoiseShader::Type type() const { return fType; }
   548     bool stitchTiles() const { return fStitchTiles; }
   549     const SkVector& baseFrequency() const { return fBaseFrequency; }
   550     int numOctaves() const { return fNumOctaves; }
   551     const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
   552     uint8_t alpha() const { return fAlpha; }
   554     void getConstantColorComponents(GrColor*, uint32_t* validFlags) const SK_OVERRIDE {
   555         *validFlags = 0; // This is noise. Nothing is constant.
   556     }
   558 protected:
   559     virtual bool onIsEqual(const GrEffect& sBase) const SK_OVERRIDE {
   560         const GrNoiseEffect& s = CastEffect<GrNoiseEffect>(sBase);
   561         return fType == s.fType &&
   562                fBaseFrequency == s.fBaseFrequency &&
   563                fNumOctaves == s.fNumOctaves &&
   564                fStitchTiles == s.fStitchTiles &&
   565                fCoordTransform.getMatrix() == s.fCoordTransform.getMatrix() &&
   566                fAlpha == s.fAlpha;
   567     }
   569     GrNoiseEffect(SkPerlinNoiseShader::Type type, const SkVector& baseFrequency, int numOctaves,
   570                   bool stitchTiles, const SkMatrix& matrix, uint8_t alpha)
   571       : fType(type)
   572       , fBaseFrequency(baseFrequency)
   573       , fNumOctaves(numOctaves)
   574       , fStitchTiles(stitchTiles)
   575       , fMatrix(matrix)
   576       , fAlpha(alpha) {
   577         // This (1,1) translation is due to WebKit's 1 based coordinates for the noise
   578         // (as opposed to 0 based, usually). The same adjustment is in the shadeSpan() functions.
   579         SkMatrix m = matrix;
   580         m.postTranslate(SK_Scalar1, SK_Scalar1);
   581         fCoordTransform.reset(kLocal_GrCoordSet, m);
   582         this->addCoordTransform(&fCoordTransform);
   583         this->setWillNotUseInputColor();
   584     }
   586     SkPerlinNoiseShader::Type       fType;
   587     GrCoordTransform                fCoordTransform;
   588     SkVector                        fBaseFrequency;
   589     int                             fNumOctaves;
   590     bool                            fStitchTiles;
   591     SkMatrix                        fMatrix;
   592     uint8_t                         fAlpha;
   594 private:
   595     typedef GrEffect INHERITED;
   596 };
   598 class GrPerlinNoiseEffect : public GrNoiseEffect {
   599 public:
   600     static GrEffectRef* Create(SkPerlinNoiseShader::Type type, const SkVector& baseFrequency,
   601                                int numOctaves, bool stitchTiles,
   602                                const SkPerlinNoiseShader::StitchData& stitchData,
   603                                GrTexture* permutationsTexture, GrTexture* noiseTexture,
   604                                const SkMatrix& matrix, uint8_t alpha) {
   605         AutoEffectUnref effect(SkNEW_ARGS(GrPerlinNoiseEffect, (type, baseFrequency, numOctaves,
   606             stitchTiles, stitchData, permutationsTexture, noiseTexture, matrix, alpha)));
   607         return CreateEffectRef(effect);
   608     }
   610     virtual ~GrPerlinNoiseEffect() { }
   612     static const char* Name() { return "PerlinNoise"; }
   613     virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
   614         return GrTBackendEffectFactory<GrPerlinNoiseEffect>::getInstance();
   615     }
   616     const SkPerlinNoiseShader::StitchData& stitchData() const { return fStitchData; }
   618     typedef GrGLPerlinNoise GLEffect;
   620 private:
   621     virtual bool onIsEqual(const GrEffect& sBase) const SK_OVERRIDE {
   622         const GrPerlinNoiseEffect& s = CastEffect<GrPerlinNoiseEffect>(sBase);
   623         return INHERITED::onIsEqual(sBase) &&
   624                fPermutationsAccess.getTexture() == s.fPermutationsAccess.getTexture() &&
   625                fNoiseAccess.getTexture() == s.fNoiseAccess.getTexture() &&
   626                fStitchData == s.fStitchData;
   627     }
   629     GrPerlinNoiseEffect(SkPerlinNoiseShader::Type type, const SkVector& baseFrequency,
   630                         int numOctaves, bool stitchTiles,
   631                         const SkPerlinNoiseShader::StitchData& stitchData,
   632                         GrTexture* permutationsTexture, GrTexture* noiseTexture,
   633                         const SkMatrix& matrix, uint8_t alpha)
   634       : GrNoiseEffect(type, baseFrequency, numOctaves, stitchTiles, matrix, alpha)
   635       , fPermutationsAccess(permutationsTexture)
   636       , fNoiseAccess(noiseTexture)
   637       , fStitchData(stitchData) {
   638         this->addTextureAccess(&fPermutationsAccess);
   639         this->addTextureAccess(&fNoiseAccess);
   640     }
   642     GR_DECLARE_EFFECT_TEST;
   644     GrTextureAccess                 fPermutationsAccess;
   645     GrTextureAccess                 fNoiseAccess;
   646     SkPerlinNoiseShader::StitchData fStitchData;
   648     typedef GrNoiseEffect INHERITED;
   649 };
   651 class GrSimplexNoiseEffect : public GrNoiseEffect {
   652     // Note : This is for reference only. GrPerlinNoiseEffect is used for processing.
   653 public:
   654     static GrEffectRef* Create(SkPerlinNoiseShader::Type type, const SkVector& baseFrequency,
   655                                int numOctaves, bool stitchTiles, const SkScalar seed,
   656                                const SkMatrix& matrix, uint8_t alpha) {
   657         AutoEffectUnref effect(SkNEW_ARGS(GrSimplexNoiseEffect, (type, baseFrequency, numOctaves,
   658             stitchTiles, seed, matrix, alpha)));
   659         return CreateEffectRef(effect);
   660     }
   662     virtual ~GrSimplexNoiseEffect() { }
   664     static const char* Name() { return "SimplexNoise"; }
   665     virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
   666         return GrTBackendEffectFactory<GrSimplexNoiseEffect>::getInstance();
   667     }
   668     const SkScalar& seed() const { return fSeed; }
   670     typedef GrGLSimplexNoise GLEffect;
   672 private:
   673     virtual bool onIsEqual(const GrEffect& sBase) const SK_OVERRIDE {
   674         const GrSimplexNoiseEffect& s = CastEffect<GrSimplexNoiseEffect>(sBase);
   675         return INHERITED::onIsEqual(sBase) && fSeed == s.fSeed;
   676     }
   678     GrSimplexNoiseEffect(SkPerlinNoiseShader::Type type, const SkVector& baseFrequency,
   679                          int numOctaves, bool stitchTiles, const SkScalar seed,
   680                          const SkMatrix& matrix, uint8_t alpha)
   681       : GrNoiseEffect(type, baseFrequency, numOctaves, stitchTiles, matrix, alpha)
   682       , fSeed(seed) {
   683     }
   685     SkScalar fSeed;
   687     typedef GrNoiseEffect INHERITED;
   688 };
   690 /////////////////////////////////////////////////////////////////////
   691 GR_DEFINE_EFFECT_TEST(GrPerlinNoiseEffect);
   693 GrEffectRef* GrPerlinNoiseEffect::TestCreate(SkRandom* random,
   694                                              GrContext* context,
   695                                              const GrDrawTargetCaps&,
   696                                              GrTexture**) {
   697     int      numOctaves = random->nextRangeU(2, 10);
   698     bool     stitchTiles = random->nextBool();
   699     SkScalar seed = SkIntToScalar(random->nextU());
   700     SkISize  tileSize = SkISize::Make(random->nextRangeU(4, 4096), random->nextRangeU(4, 4096));
   701     SkScalar baseFrequencyX = random->nextRangeScalar(0.01f,
   702                                                       0.99f);
   703     SkScalar baseFrequencyY = random->nextRangeScalar(0.01f,
   704                                                       0.99f);
   706     SkShader* shader = random->nextBool() ?
   707         SkPerlinNoiseShader::CreateFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves, seed,
   708                                                 stitchTiles ? &tileSize : NULL) :
   709         SkPerlinNoiseShader::CreateTubulence(baseFrequencyX, baseFrequencyY, numOctaves, seed,
   710                                              stitchTiles ? &tileSize : NULL);
   712     SkPaint paint;
   713     GrEffectRef* effect = shader->asNewEffect(context, paint);
   715     SkDELETE(shader);
   717     return effect;
   718 }
   720 /////////////////////////////////////////////////////////////////////
   722 void GrGLSimplexNoise::emitCode(GrGLShaderBuilder* builder,
   723                                 const GrDrawEffect&,
   724                                 EffectKey key,
   725                                 const char* outputColor,
   726                                 const char* inputColor,
   727                                 const TransformedCoordsArray& coords,
   728                                 const TextureSamplerArray&) {
   729     sk_ignore_unused_variable(inputColor);
   731     SkString vCoords = builder->ensureFSCoords2D(coords, 0);
   733     fSeedUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
   734                                    kFloat_GrSLType, "seed");
   735     const char* seedUni = builder->getUniformCStr(fSeedUni);
   736     fInvMatrixUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
   737                                         kMat33f_GrSLType, "invMatrix");
   738     const char* invMatrixUni = builder->getUniformCStr(fInvMatrixUni);
   739     fBaseFrequencyUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
   740                                             kVec2f_GrSLType, "baseFrequency");
   741     const char* baseFrequencyUni = builder->getUniformCStr(fBaseFrequencyUni);
   742     fAlphaUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
   743                                     kFloat_GrSLType, "alpha");
   744     const char* alphaUni = builder->getUniformCStr(fAlphaUni);
   746     // Add vec3 modulo 289 function
   747     static const GrGLShaderVar gVec3Args[] =  {
   748         GrGLShaderVar("x", kVec3f_GrSLType)
   749     };
   751     SkString mod289_3_funcName;
   752     builder->fsEmitFunction(kVec3f_GrSLType,
   753                             "mod289", SK_ARRAY_COUNT(gVec3Args), gVec3Args,
   754                             "const vec2 C = vec2(1.0 / 289.0, 289.0);\n"
   755                             "return x - floor(x * C.xxx) * C.yyy;", &mod289_3_funcName);
   757     // Add vec4 modulo 289 function
   758     static const GrGLShaderVar gVec4Args[] =  {
   759         GrGLShaderVar("x", kVec4f_GrSLType)
   760     };
   762     SkString mod289_4_funcName;
   763     builder->fsEmitFunction(kVec4f_GrSLType,
   764                             "mod289", SK_ARRAY_COUNT(gVec4Args), gVec4Args,
   765                             "const vec2 C = vec2(1.0 / 289.0, 289.0);\n"
   766                             "return x - floor(x * C.xxxx) * C.yyyy;", &mod289_4_funcName);
   768     // Add vec4 permute function
   769     SkString permuteCode;
   770     permuteCode.appendf("const vec2 C = vec2(34.0, 1.0);\n"
   771                         "return %s(((x * C.xxxx) + C.yyyy) * x);", mod289_4_funcName.c_str());
   772     SkString permuteFuncName;
   773     builder->fsEmitFunction(kVec4f_GrSLType,
   774                             "permute", SK_ARRAY_COUNT(gVec4Args), gVec4Args,
   775                             permuteCode.c_str(), &permuteFuncName);
   777     // Add vec4 taylorInvSqrt function
   778     SkString taylorInvSqrtFuncName;
   779     builder->fsEmitFunction(kVec4f_GrSLType,
   780                             "taylorInvSqrt", SK_ARRAY_COUNT(gVec4Args), gVec4Args,
   781                             "const vec2 C = vec2(-0.85373472095314, 1.79284291400159);\n"
   782                             "return x * C.xxxx + C.yyyy;", &taylorInvSqrtFuncName);
   784     // Add vec3 noise function
   785     static const GrGLShaderVar gNoiseVec3Args[] =  {
   786         GrGLShaderVar("v", kVec3f_GrSLType)
   787     };
   789     SkString noiseCode;
   790     noiseCode.append(
   791         "const vec2 C = vec2(1.0/6.0, 1.0/3.0);\n"
   792         "const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);\n"
   794         // First corner
   795         "vec3 i = floor(v + dot(v, C.yyy));\n"
   796         "vec3 x0 = v - i + dot(i, C.xxx);\n"
   798         // Other corners
   799         "vec3 g = step(x0.yzx, x0.xyz);\n"
   800         "vec3 l = 1.0 - g;\n"
   801         "vec3 i1 = min(g.xyz, l.zxy);\n"
   802         "vec3 i2 = max(g.xyz, l.zxy);\n"
   804         "vec3 x1 = x0 - i1 + C.xxx;\n"
   805         "vec3 x2 = x0 - i2 + C.yyy;\n" // 2.0*C.x = 1/3 = C.y
   806         "vec3 x3 = x0 - D.yyy;\n" // -1.0+3.0*C.x = -0.5 = -D.y
   807     );
   809     noiseCode.appendf(
   810         // Permutations
   811         "i = %s(i);\n"
   812         "vec4 p = %s(%s(%s(\n"
   813         "         i.z + vec4(0.0, i1.z, i2.z, 1.0)) +\n"
   814         "         i.y + vec4(0.0, i1.y, i2.y, 1.0)) +\n"
   815         "         i.x + vec4(0.0, i1.x, i2.x, 1.0));\n",
   816         mod289_3_funcName.c_str(), permuteFuncName.c_str(), permuteFuncName.c_str(),
   817         permuteFuncName.c_str());
   819     noiseCode.append(
   820         // Gradients: 7x7 points over a square, mapped onto an octahedron.
   821         // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
   822         "float n_ = 0.142857142857;\n" // 1.0/7.0
   823         "vec3  ns = n_ * D.wyz - D.xzx;\n"
   825         "vec4 j = p - 49.0 * floor(p * ns.z * ns.z);\n" // mod(p,7*7)
   827         "vec4 x_ = floor(j * ns.z);\n"
   828         "vec4 y_ = floor(j - 7.0 * x_);" // mod(j,N)
   830         "vec4 x = x_ *ns.x + ns.yyyy;\n"
   831         "vec4 y = y_ *ns.x + ns.yyyy;\n"
   832         "vec4 h = 1.0 - abs(x) - abs(y);\n"
   834         "vec4 b0 = vec4(x.xy, y.xy);\n"
   835         "vec4 b1 = vec4(x.zw, y.zw);\n"
   836     );
   838     noiseCode.append(
   839         "vec4 s0 = floor(b0) * 2.0 + 1.0;\n"
   840         "vec4 s1 = floor(b1) * 2.0 + 1.0;\n"
   841         "vec4 sh = -step(h, vec4(0.0));\n"
   843         "vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;\n"
   844         "vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww;\n"
   846         "vec3 p0 = vec3(a0.xy, h.x);\n"
   847         "vec3 p1 = vec3(a0.zw, h.y);\n"
   848         "vec3 p2 = vec3(a1.xy, h.z);\n"
   849         "vec3 p3 = vec3(a1.zw, h.w);\n"
   850     );
   852     noiseCode.appendf(
   853         // Normalise gradients
   854         "vec4 norm = %s(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));\n"
   855         "p0 *= norm.x;\n"
   856         "p1 *= norm.y;\n"
   857         "p2 *= norm.z;\n"
   858         "p3 *= norm.w;\n"
   860         // Mix final noise value
   861         "vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);\n"
   862         "m = m * m;\n"
   863         "return 42.0 * dot(m*m, vec4(dot(p0,x0), dot(p1,x1), dot(p2,x2), dot(p3,x3)));",
   864         taylorInvSqrtFuncName.c_str());
   866     SkString noiseFuncName;
   867     builder->fsEmitFunction(kFloat_GrSLType,
   868                             "snoise", SK_ARRAY_COUNT(gNoiseVec3Args), gNoiseVec3Args,
   869                             noiseCode.c_str(), &noiseFuncName);
   871     const char* noiseVecIni = "noiseVecIni";
   872     const char* factors     = "factors";
   873     const char* sum         = "sum";
   874     const char* xOffsets    = "xOffsets";
   875     const char* yOffsets    = "yOffsets";
   876     const char* channel     = "channel";
   878     // Fill with some prime numbers
   879     builder->fsCodeAppendf("\t\tconst vec4 %s = vec4(13.0, 53.0, 101.0, 151.0);\n", xOffsets);
   880     builder->fsCodeAppendf("\t\tconst vec4 %s = vec4(109.0, 167.0, 23.0, 67.0);\n", yOffsets);
   882     // There are rounding errors if the floor operation is not performed here
   883     builder->fsCodeAppendf(
   884         "\t\tvec3 %s = vec3(floor((%s*vec3(%s, 1.0)).xy) * vec2(0.66) * %s, 0.0);\n",
   885         noiseVecIni, invMatrixUni, vCoords.c_str(), baseFrequencyUni);
   887     // Perturb the texcoords with three components of noise
   888     builder->fsCodeAppendf("\t\t%s += 0.1 * vec3(%s(%s + vec3(  0.0,   0.0, %s)),"
   889                                                 "%s(%s + vec3( 43.0,  17.0, %s)),"
   890                                                 "%s(%s + vec3(-17.0, -43.0, %s)));\n",
   891                            noiseVecIni, noiseFuncName.c_str(), noiseVecIni, seedUni,
   892                                         noiseFuncName.c_str(), noiseVecIni, seedUni,
   893                                         noiseFuncName.c_str(), noiseVecIni, seedUni);
   895     builder->fsCodeAppendf("\t\t%s = vec4(0.0);\n", outputColor);
   897     builder->fsCodeAppendf("\t\tvec3 %s = vec3(1.0);\n", factors);
   898     builder->fsCodeAppendf("\t\tfloat %s = 0.0;\n", sum);
   900     // Loop over all octaves
   901     builder->fsCodeAppendf("\t\tfor (int octave = 0; octave < %d; ++octave) {\n", fNumOctaves);
   903     // Loop over the 4 channels
   904     builder->fsCodeAppendf("\t\t\tfor (int %s = 3; %s >= 0; --%s) {\n", channel, channel, channel);
   906     builder->fsCodeAppendf(
   907         "\t\t\t\t%s[channel] += %s.x * %s(%s * %s.yyy - vec3(%s[%s], %s[%s], %s * %s.z));\n",
   908         outputColor, factors, noiseFuncName.c_str(), noiseVecIni, factors, xOffsets, channel,
   909         yOffsets, channel, seedUni, factors);
   911     builder->fsCodeAppend("\t\t\t}\n"); // end of the for loop on channels
   913     builder->fsCodeAppendf("\t\t\t%s += %s.x;\n", sum, factors);
   914     builder->fsCodeAppendf("\t\t\t%s *= vec3(0.5, 2.0, 0.75);\n", factors);
   916     builder->fsCodeAppend("\t\t}\n"); // end of the for loop on octaves
   918     if (fType == SkPerlinNoiseShader::kFractalNoise_Type) {
   919         // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
   920         // by fractalNoise and (turbulenceFunctionResult) by turbulence.
   921         builder->fsCodeAppendf("\t\t%s = %s * vec4(0.5 / %s) + vec4(0.5);\n",
   922                                outputColor, outputColor, sum);
   923     } else {
   924         builder->fsCodeAppendf("\t\t%s = abs(%s / vec4(%s));\n",
   925                                outputColor, outputColor, sum);
   926     }
   928     builder->fsCodeAppendf("\t\t%s.a *= %s;\n", outputColor, alphaUni);
   930     // Clamp values
   931     builder->fsCodeAppendf("\t\t%s = clamp(%s, 0.0, 1.0);\n", outputColor, outputColor);
   933     // Pre-multiply the result
   934     builder->fsCodeAppendf("\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
   935                            outputColor, outputColor, outputColor, outputColor);
   936 }
   938 void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder,
   939                                const GrDrawEffect&,
   940                                EffectKey key,
   941                                const char* outputColor,
   942                                const char* inputColor,
   943                                const TransformedCoordsArray& coords,
   944                                const TextureSamplerArray& samplers) {
   945     sk_ignore_unused_variable(inputColor);
   947     SkString vCoords = builder->ensureFSCoords2D(coords, 0);
   949     fInvMatrixUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
   950                                         kMat33f_GrSLType, "invMatrix");
   951     const char* invMatrixUni = builder->getUniformCStr(fInvMatrixUni);
   952     fBaseFrequencyUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
   953                                             kVec2f_GrSLType, "baseFrequency");
   954     const char* baseFrequencyUni = builder->getUniformCStr(fBaseFrequencyUni);
   955     fAlphaUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
   956                                     kFloat_GrSLType, "alpha");
   957     const char* alphaUni = builder->getUniformCStr(fAlphaUni);
   959     const char* stitchDataUni = NULL;
   960     if (fStitchTiles) {
   961         fStitchDataUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
   962                                              kVec2f_GrSLType, "stitchData");
   963         stitchDataUni = builder->getUniformCStr(fStitchDataUni);
   964     }
   966     // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8
   967     const char* chanCoordR  = "0.125";
   968     const char* chanCoordG  = "0.375";
   969     const char* chanCoordB  = "0.625";
   970     const char* chanCoordA  = "0.875";
   971     const char* chanCoord   = "chanCoord";
   972     const char* stitchData  = "stitchData";
   973     const char* ratio       = "ratio";
   974     const char* noiseXY     = "noiseXY";
   975     const char* noiseVec    = "noiseVec";
   976     const char* noiseSmooth = "noiseSmooth";
   977     const char* fractVal    = "fractVal";
   978     const char* uv          = "uv";
   979     const char* ab          = "ab";
   980     const char* latticeIdx  = "latticeIdx";
   981     const char* lattice     = "lattice";
   982     const char* inc8bit     = "0.00390625";  // 1.0 / 256.0
   983     // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a
   984     // [-1,1] vector and perform a dot product between that vector and the provided vector.
   985     const char* dotLattice  = "dot(((%s.ga + %s.rb * vec2(%s)) * vec2(2.0) - vec2(1.0)), %s);";
   987     // Add noise function
   988     static const GrGLShaderVar gPerlinNoiseArgs[] =  {
   989         GrGLShaderVar(chanCoord, kFloat_GrSLType),
   990         GrGLShaderVar(noiseVec, kVec2f_GrSLType)
   991     };
   993     static const GrGLShaderVar gPerlinNoiseStitchArgs[] =  {
   994         GrGLShaderVar(chanCoord, kFloat_GrSLType),
   995         GrGLShaderVar(noiseVec, kVec2f_GrSLType),
   996         GrGLShaderVar(stitchData, kVec2f_GrSLType)
   997     };
   999     SkString noiseCode;
  1001     noiseCode.appendf("\tvec4 %s = vec4(floor(%s), fract(%s));", noiseXY, noiseVec, noiseVec);
  1003     // smooth curve : t * t * (3 - 2 * t)
  1004     noiseCode.appendf("\n\tvec2 %s = %s.zw * %s.zw * (vec2(3.0) - vec2(2.0) * %s.zw);",
  1005         noiseSmooth, noiseXY, noiseXY, noiseXY);
  1007     // Adjust frequencies if we're stitching tiles
  1008     if (fStitchTiles) {
  1009         noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }",
  1010             noiseXY, stitchData, noiseXY, stitchData);
  1011         noiseCode.appendf("\n\tif(%s.x >= (%s.x - 1.0)) { %s.x -= (%s.x - 1.0); }",
  1012             noiseXY, stitchData, noiseXY, stitchData);
  1013         noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }",
  1014             noiseXY, stitchData, noiseXY, stitchData);
  1015         noiseCode.appendf("\n\tif(%s.y >= (%s.y - 1.0)) { %s.y -= (%s.y - 1.0); }",
  1016             noiseXY, stitchData, noiseXY, stitchData);
  1019     // Get texture coordinates and normalize
  1020     noiseCode.appendf("\n\t%s.xy = fract(floor(mod(%s.xy, 256.0)) / vec2(256.0));\n",
  1021         noiseXY, noiseXY);
  1023     // Get permutation for x
  1025         SkString xCoords("");
  1026         xCoords.appendf("vec2(%s.x, 0.5)", noiseXY);
  1028         noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
  1029         builder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType);
  1030         noiseCode.append(".r;");
  1033     // Get permutation for x + 1
  1035         SkString xCoords("");
  1036         xCoords.appendf("vec2(fract(%s.x + %s), 0.5)", noiseXY, inc8bit);
  1038         noiseCode.appendf("\n\t%s.y = ", latticeIdx);
  1039         builder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType);
  1040         noiseCode.append(".r;");
  1043 #if defined(SK_BUILD_FOR_ANDROID)
  1044     // Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3).
  1045     // The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit
  1046     // value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725
  1047     // (or 0.484368 here). The following rounding operation prevents these precision issues from
  1048     // affecting the result of the noise by making sure that we only have multiples of 1/255.
  1049     // (Note that 1/255 is about 0.003921569, which is the value used here).
  1050     noiseCode.appendf("\n\t%s = floor(%s * vec2(255.0) + vec2(0.5)) * vec2(0.003921569);",
  1051                       latticeIdx, latticeIdx);
  1052 #endif
  1054     // Get (x,y) coordinates with the permutated x
  1055     noiseCode.appendf("\n\t%s = fract(%s + %s.yy);", latticeIdx, latticeIdx, noiseXY);
  1057     noiseCode.appendf("\n\tvec2 %s = %s.zw;", fractVal, noiseXY);
  1059     noiseCode.appendf("\n\n\tvec2 %s;", uv);
  1060     // Compute u, at offset (0,0)
  1062         SkString latticeCoords("");
  1063         latticeCoords.appendf("vec2(%s.x, %s)", latticeIdx, chanCoord);
  1064         noiseCode.appendf("\n\tvec4 %s = ", lattice);
  1065         builder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
  1066             kVec2f_GrSLType);
  1067         noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
  1068         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
  1071     noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal);
  1072     // Compute v, at offset (-1,0)
  1074         SkString latticeCoords("");
  1075         latticeCoords.appendf("vec2(%s.y, %s)", latticeIdx, chanCoord);
  1076         noiseCode.append("\n\tlattice = ");
  1077         builder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
  1078             kVec2f_GrSLType);
  1079         noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
  1080         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
  1083     // Compute 'a' as a linear interpolation of 'u' and 'v'
  1084     noiseCode.appendf("\n\tvec2 %s;", ab);
  1085     noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
  1087     noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal);
  1088     // Compute v, at offset (-1,-1)
  1090         SkString latticeCoords("");
  1091         latticeCoords.appendf("vec2(fract(%s.y + %s), %s)", latticeIdx, inc8bit, chanCoord);
  1092         noiseCode.append("\n\tlattice = ");
  1093         builder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
  1094             kVec2f_GrSLType);
  1095         noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
  1096         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
  1099     noiseCode.appendf("\n\t%s.x += 1.0;", fractVal);
  1100     // Compute u, at offset (0,-1)
  1102         SkString latticeCoords("");
  1103         latticeCoords.appendf("vec2(fract(%s.x + %s), %s)", latticeIdx, inc8bit, chanCoord);
  1104         noiseCode.append("\n\tlattice = ");
  1105         builder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
  1106             kVec2f_GrSLType);
  1107         noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
  1108         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
  1111     // Compute 'b' as a linear interpolation of 'u' and 'v'
  1112     noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
  1113     // Compute the noise as a linear interpolation of 'a' and 'b'
  1114     noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth);
  1116     SkString noiseFuncName;
  1117     if (fStitchTiles) {
  1118         builder->fsEmitFunction(kFloat_GrSLType,
  1119                                 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs),
  1120                                 gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName);
  1121     } else {
  1122         builder->fsEmitFunction(kFloat_GrSLType,
  1123                                 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs),
  1124                                 gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName);
  1127     // There are rounding errors if the floor operation is not performed here
  1128     builder->fsCodeAppendf("\n\t\tvec2 %s = floor((%s * vec3(%s, 1.0)).xy) * %s;",
  1129                            noiseVec, invMatrixUni, vCoords.c_str(), baseFrequencyUni);
  1131     // Clear the color accumulator
  1132     builder->fsCodeAppendf("\n\t\t%s = vec4(0.0);", outputColor);
  1134     if (fStitchTiles) {
  1135         // Set up TurbulenceInitial stitch values.
  1136         builder->fsCodeAppendf("\n\t\tvec2 %s = %s;", stitchData, stitchDataUni);
  1139     builder->fsCodeAppendf("\n\t\tfloat %s = 1.0;", ratio);
  1141     // Loop over all octaves
  1142     builder->fsCodeAppendf("\n\t\tfor (int octave = 0; octave < %d; ++octave) {", fNumOctaves);
  1144     builder->fsCodeAppendf("\n\t\t\t%s += ", outputColor);
  1145     if (fType != SkPerlinNoiseShader::kFractalNoise_Type) {
  1146         builder->fsCodeAppend("abs(");
  1148     if (fStitchTiles) {
  1149         builder->fsCodeAppendf(
  1150             "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s),"
  1151                  "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))",
  1152             noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData,
  1153             noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData,
  1154             noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData,
  1155             noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData);
  1156     } else {
  1157         builder->fsCodeAppendf(
  1158             "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s),"
  1159                  "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))",
  1160             noiseFuncName.c_str(), chanCoordR, noiseVec,
  1161             noiseFuncName.c_str(), chanCoordG, noiseVec,
  1162             noiseFuncName.c_str(), chanCoordB, noiseVec,
  1163             noiseFuncName.c_str(), chanCoordA, noiseVec);
  1165     if (fType != SkPerlinNoiseShader::kFractalNoise_Type) {
  1166         builder->fsCodeAppendf(")"); // end of "abs("
  1168     builder->fsCodeAppendf(" * %s;", ratio);
  1170     builder->fsCodeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec);
  1171     builder->fsCodeAppendf("\n\t\t\t%s *= 0.5;", ratio);
  1173     if (fStitchTiles) {
  1174         builder->fsCodeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData);
  1176     builder->fsCodeAppend("\n\t\t}"); // end of the for loop on octaves
  1178     if (fType == SkPerlinNoiseShader::kFractalNoise_Type) {
  1179         // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
  1180         // by fractalNoise and (turbulenceFunctionResult) by turbulence.
  1181         builder->fsCodeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);", outputColor, outputColor);
  1184     builder->fsCodeAppendf("\n\t\t%s.a *= %s;", outputColor, alphaUni);
  1186     // Clamp values
  1187     builder->fsCodeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", outputColor, outputColor);
  1189     // Pre-multiply the result
  1190     builder->fsCodeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
  1191                   outputColor, outputColor, outputColor, outputColor);
  1194 GrGLNoise::GrGLNoise(const GrBackendEffectFactory& factory, const GrDrawEffect& drawEffect)
  1195   : INHERITED (factory)
  1196   , fType(drawEffect.castEffect<GrPerlinNoiseEffect>().type())
  1197   , fStitchTiles(drawEffect.castEffect<GrPerlinNoiseEffect>().stitchTiles())
  1198   , fNumOctaves(drawEffect.castEffect<GrPerlinNoiseEffect>().numOctaves()) {
  1201 GrGLEffect::EffectKey GrGLNoise::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
  1202     const GrPerlinNoiseEffect& turbulence = drawEffect.castEffect<GrPerlinNoiseEffect>();
  1204     EffectKey key = turbulence.numOctaves();
  1206     key = key << 3; // Make room for next 3 bits
  1208     switch (turbulence.type()) {
  1209         case SkPerlinNoiseShader::kFractalNoise_Type:
  1210             key |= 0x1;
  1211             break;
  1212         case SkPerlinNoiseShader::kTurbulence_Type:
  1213             key |= 0x2;
  1214             break;
  1215         default:
  1216             // leave key at 0
  1217             break;
  1220     if (turbulence.stitchTiles()) {
  1221         key |= 0x4; // Flip the 3rd bit if tile stitching is on
  1224     return key;
  1227 void GrGLNoise::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) {
  1228     const GrPerlinNoiseEffect& turbulence = drawEffect.castEffect<GrPerlinNoiseEffect>();
  1230     const SkVector& baseFrequency = turbulence.baseFrequency();
  1231     uman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
  1232     uman.set1f(fAlphaUni, SkScalarDiv(SkIntToScalar(turbulence.alpha()), SkIntToScalar(255)));
  1234     SkMatrix m = turbulence.matrix();
  1235     m.postTranslate(-SK_Scalar1, -SK_Scalar1);
  1236     SkMatrix invM;
  1237     if (!m.invert(&invM)) {
  1238         invM.reset();
  1239     } else {
  1240         invM.postConcat(invM); // Square the matrix
  1242     uman.setSkMatrix(fInvMatrixUni, invM);
  1245 void GrGLPerlinNoise::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) {
  1246     INHERITED::setData(uman, drawEffect);
  1248     const GrPerlinNoiseEffect& turbulence = drawEffect.castEffect<GrPerlinNoiseEffect>();
  1249     if (turbulence.stitchTiles()) {
  1250         const SkPerlinNoiseShader::StitchData& stitchData = turbulence.stitchData();
  1251         uman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth),
  1252                                    SkIntToScalar(stitchData.fHeight));
  1256 void GrGLSimplexNoise::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) {
  1257     INHERITED::setData(uman, drawEffect);
  1259     const GrSimplexNoiseEffect& turbulence = drawEffect.castEffect<GrSimplexNoiseEffect>();
  1260     uman.set1f(fSeedUni, turbulence.seed());
  1263 /////////////////////////////////////////////////////////////////////
  1265 GrEffectRef* SkPerlinNoiseShader::asNewEffect(GrContext* context, const SkPaint& paint) const {
  1266     SkASSERT(NULL != context);
  1268     if (0 == fNumOctaves) {
  1269         SkColor clearColor = 0;
  1270         if (kFractalNoise_Type == fType) {
  1271             clearColor = SkColorSetARGB(paint.getAlpha() / 2, 127, 127, 127);
  1273         SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(
  1274                                                 clearColor, SkXfermode::kSrc_Mode));
  1275         return cf->asNewEffect(context);
  1278     // Either we don't stitch tiles, either we have a valid tile size
  1279     SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
  1281 #ifdef SK_USE_SIMPLEX_NOISE
  1282     // Simplex noise is currently disabled but can be enabled by defining SK_USE_SIMPLEX_NOISE
  1283     sk_ignore_unused_variable(context);
  1284     GrEffectRef* effect =
  1285         GrSimplexNoiseEffect::Create(fType, fPaintingData->fBaseFrequency,
  1286                                      fNumOctaves, fStitchTiles, fSeed,
  1287                                      this->getLocalMatrix(), paint.getAlpha());
  1288 #else
  1289     GrTexture* permutationsTexture = GrLockAndRefCachedBitmapTexture(
  1290         context, fPaintingData->getPermutationsBitmap(), NULL);
  1291     GrTexture* noiseTexture = GrLockAndRefCachedBitmapTexture(
  1292         context, fPaintingData->getNoiseBitmap(), NULL);
  1294     GrEffectRef* effect = (NULL != permutationsTexture) && (NULL != noiseTexture) ?
  1295         GrPerlinNoiseEffect::Create(fType, fPaintingData->fBaseFrequency,
  1296                                     fNumOctaves, fStitchTiles,
  1297                                     fPaintingData->fStitchDataInit,
  1298                                     permutationsTexture, noiseTexture,
  1299                                     this->getLocalMatrix(), paint.getAlpha()) :
  1300         NULL;
  1302     // Unlock immediately, this is not great, but we don't have a way of
  1303     // knowing when else to unlock it currently. TODO: Remove this when
  1304     // unref becomes the unlock replacement for all types of textures.
  1305     if (NULL != permutationsTexture) {
  1306         GrUnlockAndUnrefCachedBitmapTexture(permutationsTexture);
  1308     if (NULL != noiseTexture) {
  1309         GrUnlockAndUnrefCachedBitmapTexture(noiseTexture);
  1311 #endif
  1313     return effect;
  1316 #else
  1318 GrEffectRef* SkPerlinNoiseShader::asNewEffect(GrContext*, const SkPaint&) const {
  1319     SkDEBUGFAIL("Should not call in GPU-less build");
  1320     return NULL;
  1323 #endif
  1325 #ifndef SK_IGNORE_TO_STRING
  1326 void SkPerlinNoiseShader::toString(SkString* str) const {
  1327     str->append("SkPerlinNoiseShader: (");
  1329     str->append("type: ");
  1330     switch (fType) {
  1331         case kFractalNoise_Type:
  1332             str->append("\"fractal noise\"");
  1333             break;
  1334         case kTurbulence_Type:
  1335             str->append("\"turbulence\"");
  1336             break;
  1337         default:
  1338             str->append("\"unknown\"");
  1339             break;
  1341     str->append(" base frequency: (");
  1342     str->appendScalar(fBaseFrequencyX);
  1343     str->append(", ");
  1344     str->appendScalar(fBaseFrequencyY);
  1345     str->append(") number of octaves: ");
  1346     str->appendS32(fNumOctaves);
  1347     str->append(" seed: ");
  1348     str->appendScalar(fSeed);
  1349     str->append(" stitch tiles: ");
  1350     str->append(fStitchTiles ? "true " : "false ");
  1352     this->INHERITED::toString(str);
  1354     str->append(")");
  1356 #endif

mercurial