Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(122)

Side by Side Diff: src/effects/SkPerlinNoiseShader.cpp

Issue 169973002: Begin making SkPerlinNoiseShader const. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Make methods const and simplify const comments. Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2013 Google Inc. 2 * Copyright 2013 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkDither.h" 8 #include "SkDither.h"
9 #include "SkPerlinNoiseShader.h" 9 #include "SkPerlinNoiseShader.h"
10 #include "SkColorFilter.h" 10 #include "SkColorFilter.h"
11 #include "SkReadBuffer.h" 11 #include "SkReadBuffer.h"
12 #include "SkWriteBuffer.h" 12 #include "SkWriteBuffer.h"
13 #include "SkShader.h" 13 #include "SkShader.h"
14 #include "SkUnPreMultiply.h" 14 #include "SkUnPreMultiply.h"
15 #include "SkString.h" 15 #include "SkString.h"
16 16
17 #if SK_SUPPORT_GPU 17 #if SK_SUPPORT_GPU
18 #include "GrContext.h" 18 #include "GrContext.h"
19 #include "GrCoordTransform.h" 19 #include "GrCoordTransform.h"
20 #include "gl/GrGLEffect.h" 20 #include "gl/GrGLEffect.h"
21 #include "GrTBackendEffectFactory.h" 21 #include "GrTBackendEffectFactory.h"
22 #include "SkGr.h" 22 #include "SkGr.h"
23 #endif 23 #endif
24 24
25 static const int kBlockSize = 256; 25 const int SkPerlinNoiseShader::kBlockSize;
26 static const int kBlockMask = kBlockSize - 1; 26 const int SkPerlinNoiseShader::kBlockMask;
27 static const int kPerlinNoise = 4096; 27 static const int kPerlinNoise = 4096;
28 static const int kRandMaximum = SK_MaxS32; // 2**31 - 1 28 static const int kRandMaximum = SK_MaxS32; // 2**31 - 1
29 29
30 namespace { 30 namespace {
31 31
32 // noiseValue is the color component's value (or color) 32 // noiseValue is the color component's value (or color)
33 // limitValue is the maximum perlin noise array index value allowed 33 // limitValue is the maximum perlin noise array index value allowed
34 // newValue is the current noise dimension (either width or height) 34 // newValue is the current noise dimension (either width or height)
35 inline int checkNoise(int noiseValue, int limitValue, int newValue) { 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 arra y while we are 36 // If the noise value would bring us out of bounds of the current noise arra y while we are
(...skipping 15 matching lines...) Expand all
52 return SkScalarMul(SkScalarSquare(t), SK_Scalar3 - 2 * t); 52 return SkScalarMul(SkScalarSquare(t), SK_Scalar3 - 2 * t);
53 } 53 }
54 54
55 bool perlin_noise_type_is_valid(SkPerlinNoiseShader::Type type) { 55 bool perlin_noise_type_is_valid(SkPerlinNoiseShader::Type type) {
56 return (SkPerlinNoiseShader::kFractalNoise_Type == type) || 56 return (SkPerlinNoiseShader::kFractalNoise_Type == type) ||
57 (SkPerlinNoiseShader::kTurbulence_Type == type); 57 (SkPerlinNoiseShader::kTurbulence_Type == type);
58 } 58 }
59 59
60 } // end namespace 60 } // end namespace
61 61
62 struct SkPerlinNoiseShader::StitchData { 62 inline int random(int* seed) {
63 StitchData() 63 static const int gRandAmplitude = 16807; // 7**5; primitive root of m
64 : fWidth(0) 64 static const int gRandQ = 127773; // m / a
65 , fWrapX(0) 65 static const int gRandR = 2836; // m % a
66 , fHeight(0)
67 , fWrapY(0)
68 {}
69 66
70 bool operator==(const StitchData& other) const { 67 int result = gRandAmplitude * (*seed % gRandQ) - gRandR * (*seed / gRandQ);
71 return fWidth == other.fWidth && 68 if (result <= 0) {
72 fWrapX == other.fWrapX && 69 result += kRandMaximum;
73 fHeight == other.fHeight && 70 }
74 fWrapY == other.fWrapY; 71 *seed = result;
72 return result;
73 }
74
75 // Only called once. Could be part of the constructor.
76 void SkPerlinNoiseShader::init()
77 {
78 static const SkScalar gInvBlockSizef = SkScalarInvert(SkIntToScalar(kBlockSi ze));
79
80 // The seed value clamp to the range [1, kRandMaximum - 1].
81 if (fSeed <= 0) {
82 fSeed = -(fSeed % (kRandMaximum - 1)) + 1;
83 }
84 if (fSeed > kRandMaximum - 1) {
85 fSeed = kRandMaximum - 1;
86 }
87 for (int channel = 0; channel < 4; ++channel) {
88 for (int i = 0; i < kBlockSize; ++i) {
89 fLatticeSelector[i] = i;
90 fNoise[channel][i][0] = (random(&fSeed) % (2 * kBlockSize));
91 fNoise[channel][i][1] = (random(&fSeed) % (2 * kBlockSize));
92 }
93 }
94 for (int i = kBlockSize - 1; i > 0; --i) {
95 int k = fLatticeSelector[i];
96 int j = random(&fSeed) % kBlockSize;
97 SkASSERT(j >= 0);
98 SkASSERT(j < kBlockSize);
99 fLatticeSelector[i] = fLatticeSelector[j];
100 fLatticeSelector[j] = k;
75 } 101 }
76 102
77 int fWidth; // How much to subtract to wrap for stitching. 103 // Perform the permutations now
78 int fWrapX; // Minimum value to wrap.
79 int fHeight;
80 int fWrapY;
81 };
82
83 struct SkPerlinNoiseShader::PaintingData {
84 PaintingData(const SkISize& tileSize)
85 : fSeed(0)
86 , fTileSize(tileSize)
87 , fPermutationsBitmap(NULL)
88 , fNoiseBitmap(NULL)
89 {}
90
91 ~PaintingData()
92 { 104 {
93 SkDELETE(fPermutationsBitmap); 105 // Copy noise data
94 SkDELETE(fNoiseBitmap); 106 uint16_t noise[4][kBlockSize][2];
95 } 107 for (int i = 0; i < kBlockSize; ++i) {
96 108 for (int channel = 0; channel < 4; ++channel) {
97 int fSeed; 109 for (int j = 0; j < 2; ++j) {
98 uint8_t fLatticeSelector[kBlockSize]; 110 noise[channel][i][j] = fNoise[channel][i][j];
99 uint16_t fNoise[4][kBlockSize][2];
100 SkPoint fGradient[4][kBlockSize];
101 SkISize fTileSize;
102 SkVector fBaseFrequency;
103 StitchData fStitchDataInit;
104
105 private:
106
107 SkBitmap* fPermutationsBitmap;
108 SkBitmap* fNoiseBitmap;
109
110 public:
111
112 inline int random() {
113 static const int gRandAmplitude = 16807; // 7**5; primitive root of m
114 static const int gRandQ = 127773; // m / a
115 static const int gRandR = 2836; // m % a
116
117 int result = gRandAmplitude * (fSeed % gRandQ) - gRandR * (fSeed / gRand Q);
118 if (result <= 0)
119 result += kRandMaximum;
120 fSeed = result;
121 return result;
122 }
123
124 void init(SkScalar seed)
125 {
126 static const SkScalar gInvBlockSizef = SkScalarInvert(SkIntToScalar(kBlo ckSize));
127
128 // According to the SVG spec, we must truncate (not round) the seed valu e.
129 fSeed = SkScalarTruncToInt(seed);
130 // The seed value clamp to the range [1, kRandMaximum - 1].
131 if (fSeed <= 0) {
132 fSeed = -(fSeed % (kRandMaximum - 1)) + 1;
133 }
134 if (fSeed > kRandMaximum - 1) {
135 fSeed = kRandMaximum - 1;
136 }
137 for (int channel = 0; channel < 4; ++channel) {
138 for (int i = 0; i < kBlockSize; ++i) {
139 fLatticeSelector[i] = i;
140 fNoise[channel][i][0] = (random() % (2 * kBlockSize));
141 fNoise[channel][i][1] = (random() % (2 * kBlockSize));
142 }
143 }
144 for (int i = kBlockSize - 1; i > 0; --i) {
145 int k = fLatticeSelector[i];
146 int j = random() % kBlockSize;
147 SkASSERT(j >= 0);
148 SkASSERT(j < kBlockSize);
149 fLatticeSelector[i] = fLatticeSelector[j];
150 fLatticeSelector[j] = k;
151 }
152
153 // Perform the permutations now
154 {
155 // Copy noise data
156 uint16_t noise[4][kBlockSize][2];
157 for (int i = 0; i < kBlockSize; ++i) {
158 for (int channel = 0; channel < 4; ++channel) {
159 for (int j = 0; j < 2; ++j) {
160 noise[channel][i][j] = fNoise[channel][i][j];
161 }
162 }
163 }
164 // Do permutations on noise data
165 for (int i = 0; i < kBlockSize; ++i) {
166 for (int channel = 0; channel < 4; ++channel) {
167 for (int j = 0; j < 2; ++j) {
168 fNoise[channel][i][j] = noise[channel][fLatticeSelector[ i]][j];
169 }
170 } 111 }
171 } 112 }
172 } 113 }
114 // Do permutations on noise data
115 for (int i = 0; i < kBlockSize; ++i) {
116 for (int channel = 0; channel < 4; ++channel) {
117 for (int j = 0; j < 2; ++j) {
118 fNoise[channel][i][j] = noise[channel][fLatticeSelector[ i]][j];
119 }
120 }
121 }
122 }
173 123
174 // Half of the largest possible value for 16 bit unsigned int 124 // Half of the largest possible value for 16 bit unsigned int
175 static const SkScalar gHalfMax16bits = 32767.5f; 125 static const SkScalar gHalfMax16bits = 32767.5f;
176 126
177 // Compute gradients from permutated noise data 127 // Compute gradients from permutated noise data
178 for (int channel = 0; channel < 4; ++channel) { 128 for (int channel = 0; channel < 4; ++channel) {
179 for (int i = 0; i < kBlockSize; ++i) { 129 for (int i = 0; i < kBlockSize; ++i) {
180 fGradient[channel][i] = SkPoint::Make( 130 fGradient[channel][i] = SkPoint::Make(
181 SkScalarMul(SkIntToScalar(fNoise[channel][i][0] - kBlockSize ), 131 SkScalarMul(SkIntToScalar(fNoise[channel][i][0] - kBlockSize ),
182 gInvBlockSizef), 132 gInvBlockSizef),
183 SkScalarMul(SkIntToScalar(fNoise[channel][i][1] - kBlockSize ), 133 SkScalarMul(SkIntToScalar(fNoise[channel][i][1] - kBlockSize ),
184 gInvBlockSizef)); 134 gInvBlockSizef));
185 fGradient[channel][i].normalize(); 135 fGradient[channel][i].normalize();
186 // Put the normalized gradient back into the noise data 136 // Put the normalized gradient back into the noise data
187 fNoise[channel][i][0] = SkScalarRoundToInt(SkScalarMul( 137 fNoise[channel][i][0] = SkScalarRoundToInt(SkScalarMul(
188 fGradient[channel][i].fX + SK_Scalar1, gHalfMax16bits)); 138 fGradient[channel][i].fX + SK_Scalar1, gHalfMax16bits));
189 fNoise[channel][i][1] = SkScalarRoundToInt(SkScalarMul( 139 fNoise[channel][i][1] = SkScalarRoundToInt(SkScalarMul(
190 fGradient[channel][i].fY + SK_Scalar1, gHalfMax16bits)); 140 fGradient[channel][i].fY + SK_Scalar1, gHalfMax16bits));
191 }
192 } 141 }
193
194 // Invalidate bitmaps
195 SkDELETE(fPermutationsBitmap);
196 fPermutationsBitmap = NULL;
197 SkDELETE(fNoiseBitmap);
198 fNoiseBitmap = NULL;
199 } 142 }
200 143
201 void stitch() { 144 if (fTileSize.isEmpty()) {
scroggo 2014/03/04 22:26:34 stitch() is now part of init.
202 SkScalar tileWidth = SkIntToScalar(fTileSize.width()); 145 return;
203 SkScalar tileHeight = SkIntToScalar(fTileSize.height());
204 SkASSERT(tileWidth > 0 && tileHeight > 0);
205 // When stitching tiled turbulence, the frequencies must be adjusted
206 // so that the tile borders will be continuous.
207 if (fBaseFrequency.fX) {
208 SkScalar lowFrequencx =
209 SkScalarFloorToScalar(tileWidth * fBaseFrequency.fX) / tileWidth ;
210 SkScalar highFrequencx =
211 SkScalarCeilToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
212 // BaseFrequency should be non-negative according to the standard.
213 if (SkScalarDiv(fBaseFrequency.fX, lowFrequencx) <
214 SkScalarDiv(highFrequencx, fBaseFrequency.fX)) {
215 fBaseFrequency.fX = lowFrequencx;
216 } else {
217 fBaseFrequency.fX = highFrequencx;
218 }
219 }
220 if (fBaseFrequency.fY) {
221 SkScalar lowFrequency =
222 SkScalarFloorToScalar(tileHeight * fBaseFrequency.fY) / tileHeig ht;
223 SkScalar highFrequency =
224 SkScalarCeilToScalar(tileHeight * fBaseFrequency.fY) / tileHeigh t;
225 if (SkScalarDiv(fBaseFrequency.fY, lowFrequency) <
226 SkScalarDiv(highFrequency, fBaseFrequency.fY)) {
227 fBaseFrequency.fY = lowFrequency;
228 } else {
229 fBaseFrequency.fY = highFrequency;
230 }
231 }
232 // Set up TurbulenceInitial stitch values.
233 fStitchDataInit.fWidth =
234 SkScalarRoundToInt(tileWidth * fBaseFrequency.fX);
235 fStitchDataInit.fWrapX = kPerlinNoise + fStitchDataInit.fWidth;
236 fStitchDataInit.fHeight =
237 SkScalarRoundToInt(tileHeight * fBaseFrequency.fY);
238 fStitchDataInit.fWrapY = kPerlinNoise + fStitchDataInit.fHeight;
239 } 146 }
240 147
241 SkBitmap* getPermutationsBitmap() 148 SkScalar tileWidth = SkIntToScalar(fTileSize.width());
242 { 149 SkScalar tileHeight = SkIntToScalar(fTileSize.height());
243 if (!fPermutationsBitmap) { 150 SkASSERT(tileWidth > 0 && tileHeight > 0);
244 fPermutationsBitmap = SkNEW(SkBitmap); 151 // When stitching tiled turbulence, the frequencies must be adjusted
245 fPermutationsBitmap->allocPixels(SkImageInfo::MakeA8(kBlockSize, 1)) ; 152 // so that the tile borders will be continuous.
246 uint8_t* bitmapPixels = fPermutationsBitmap->getAddr8(0, 0); 153 if (fBaseFrequency.fX) {
247 memcpy(bitmapPixels, fLatticeSelector, sizeof(uint8_t) * kBlockSize) ; 154 SkScalar lowFrequencx =
155 SkScalarFloorToScalar(tileWidth * fBaseFrequency.fX) / tileWidth ;
156 SkScalar highFrequencx =
157 SkScalarCeilToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
158 // BaseFrequency should be non-negative according to the standard.
159 if (SkScalarDiv(fBaseFrequency.fX, lowFrequencx) <
160 SkScalarDiv(highFrequencx, fBaseFrequency.fX)) {
161 fBaseFrequency.fX = lowFrequencx;
162 } else {
163 fBaseFrequency.fX = highFrequencx;
248 } 164 }
249 return fPermutationsBitmap;
250 } 165 }
166 if (fBaseFrequency.fY) {
167 SkScalar lowFrequency =
168 SkScalarFloorToScalar(tileHeight * fBaseFrequency.fY) / tileHeig ht;
169 SkScalar highFrequency =
170 SkScalarCeilToScalar(tileHeight * fBaseFrequency.fY) / tileHeigh t;
171 if (SkScalarDiv(fBaseFrequency.fY, lowFrequency) <
172 SkScalarDiv(highFrequency, fBaseFrequency.fY)) {
173 fBaseFrequency.fY = lowFrequency;
174 } else {
175 fBaseFrequency.fY = highFrequency;
176 }
177 }
178 // Set up TurbulenceInitial stitch values.
179 fStitchDataInit.fWidth =
180 SkScalarRoundToInt(tileWidth * fBaseFrequency.fX);
181 fStitchDataInit.fWrapX = kPerlinNoise + fStitchDataInit.fWidth;
182 fStitchDataInit.fHeight =
183 SkScalarRoundToInt(tileHeight * fBaseFrequency.fY);
184 fStitchDataInit.fWrapY = kPerlinNoise + fStitchDataInit.fHeight;
185 }
251 186
252 SkBitmap* getNoiseBitmap() 187 const SkBitmap& SkPerlinNoiseShader::getPermutationsBitmap() const {
253 { 188 if (kUnknown_SkColorType == fPermutationsBitmap.colorType()) {
254 if (!fNoiseBitmap) { 189 // initialize the cache.
255 fNoiseBitmap = SkNEW(SkBitmap); 190 fPermutationsBitmap.allocPixels(SkImageInfo::MakeA8(kBlockSize, 1));
256 fNoiseBitmap->allocPixels(SkImageInfo::MakeN32Premul(kBlockSize, 4)) ; 191 uint8_t* bitmapPixels = fPermutationsBitmap.getAddr8(0, 0);
257 uint32_t* bitmapPixels = fNoiseBitmap->getAddr32(0, 0); 192 memcpy(bitmapPixels, fLatticeSelector, sizeof(uint8_t) * kBlockSize);
258 memcpy(bitmapPixels, fNoise[0][0], sizeof(uint16_t) * kBlockSize * 4 * 2);
259 }
260 return fNoiseBitmap;
261 } 193 }
262 }; 194 return fPermutationsBitmap;
195 }
196
197 const SkBitmap& SkPerlinNoiseShader::getNoiseBitmap() const {
198 if (kUnknown_SkColorType == fNoiseBitmap.colorType()) {
199 // initialize the cache.
200 fNoiseBitmap.allocPixels(SkImageInfo::MakeN32Premul(kBlockSize, 4));
201 uint32_t* bitmapPixels = fNoiseBitmap.getAddr32(0, 0);
202 memcpy(bitmapPixels, fNoise[0][0], sizeof(uint16_t) * kBlockSize * 4 * 2 );
203 }
204 return fNoiseBitmap;
205 }
263 206
264 SkShader* SkPerlinNoiseShader::CreateFractalNoise(SkScalar baseFrequencyX, SkSca lar baseFrequencyY, 207 SkShader* SkPerlinNoiseShader::CreateFractalNoise(SkScalar baseFrequencyX, SkSca lar baseFrequencyY,
265 int numOctaves, SkScalar seed, 208 int numOctaves, SkScalar seed,
266 const SkISize* tileSize) { 209 const SkISize* tileSize) {
267 return SkNEW_ARGS(SkPerlinNoiseShader, (kFractalNoise_Type, baseFrequencyX, baseFrequencyY, 210 return SkNEW_ARGS(SkPerlinNoiseShader, (kFractalNoise_Type, baseFrequencyX, baseFrequencyY,
268 numOctaves, seed, tileSize)); 211 numOctaves, seed, tileSize));
269 } 212 }
270 213
271 SkShader* SkPerlinNoiseShader::CreateTubulence(SkScalar baseFrequencyX, SkScalar baseFrequencyY, 214 SkShader* SkPerlinNoiseShader::CreateTubulence(SkScalar baseFrequencyX, SkScalar baseFrequencyY,
272 int numOctaves, SkScalar seed, 215 int numOctaves, SkScalar seed,
273 const SkISize* tileSize) { 216 const SkISize* tileSize) {
274 return SkNEW_ARGS(SkPerlinNoiseShader, (kTurbulence_Type, baseFrequencyX, ba seFrequencyY, 217 return SkNEW_ARGS(SkPerlinNoiseShader, (kTurbulence_Type, baseFrequencyX, ba seFrequencyY,
275 numOctaves, seed, tileSize)); 218 numOctaves, seed, tileSize));
276 } 219 }
277 220
278 SkPerlinNoiseShader::SkPerlinNoiseShader(SkPerlinNoiseShader::Type type, 221 SkPerlinNoiseShader::SkPerlinNoiseShader(SkPerlinNoiseShader::Type type,
279 SkScalar baseFrequencyX, 222 SkScalar baseFrequencyX,
280 SkScalar baseFrequencyY, 223 SkScalar baseFrequencyY,
281 int numOctaves, 224 int numOctaves,
282 SkScalar seed, 225 SkScalar seed,
283 const SkISize* tileSize) 226 const SkISize* tileSize)
284 : fType(type) 227 : fType(type)
285 , fBaseFrequencyX(baseFrequencyX) 228 , fBaseFrequency(SkPoint::Make(baseFrequencyX, baseFrequencyY))
286 , fBaseFrequencyY(baseFrequencyY)
287 , fNumOctaves(numOctaves > 255 ? 255 : numOctaves/*[0,255] octaves allowed*/) 229 , fNumOctaves(numOctaves > 255 ? 255 : numOctaves/*[0,255] octaves allowed*/)
288 , fSeed(seed) 230 // According to the SVG spec, we must truncate (not round) the seed value.
289 , fStitchTiles((tileSize != NULL) && !tileSize->isEmpty()) 231 , fSeed(SkScalarTruncToInt(seed))
290 , fPaintingData(NULL) 232 , fTileSize(NULL == tileSize ? SkISize::Make(0, 0) : *tileSize)
233 , fStitchTiles(!fTileSize.isEmpty())
291 { 234 {
292 SkASSERT(numOctaves >= 0 && numOctaves < 256); 235 SkASSERT(numOctaves >= 0 && numOctaves < 256);
293 setTileSize(fStitchTiles ? *tileSize : SkISize::Make(0,0));
294 fMatrix.reset(); 236 fMatrix.reset();
237 this->init();
295 } 238 }
296 239
297 SkPerlinNoiseShader::SkPerlinNoiseShader(SkReadBuffer& buffer) : 240 SkPerlinNoiseShader::SkPerlinNoiseShader(SkReadBuffer& buffer)
298 INHERITED(buffer), fPaintingData(NULL) { 241 : INHERITED(buffer)
242 {
299 fType = (SkPerlinNoiseShader::Type) buffer.readInt(); 243 fType = (SkPerlinNoiseShader::Type) buffer.readInt();
300 fBaseFrequencyX = buffer.readScalar(); 244 buffer.readPoint(&fBaseFrequency);
301 fBaseFrequencyY = buffer.readScalar();
302 fNumOctaves = buffer.readInt(); 245 fNumOctaves = buffer.readInt();
303 fSeed = buffer.readScalar(); 246 fSeed = buffer.readInt();
Stephen White 2014/03/05 14:32:58 Hmmm. Isn't this going to require an SkPicture ver
sugoi 2014/03/05 16:50:33 Hmmm... In this const shader world, is there no wa
scroggo 2014/03/05 18:24:05 What do you mean by "later on during processing?"
scroggo 2014/03/05 18:24:05 Yes, this would require a picture version bump. In
304 fStitchTiles = buffer.readBool(); 247 fStitchTiles = buffer.readBool();
305 fTileSize.fWidth = buffer.readInt(); 248 fTileSize.fWidth = buffer.readInt();
306 fTileSize.fHeight = buffer.readInt(); 249 fTileSize.fHeight = buffer.readInt();
307 setTileSize(fTileSize);
308 fMatrix.reset(); 250 fMatrix.reset();
251 this->init();
309 buffer.validate(perlin_noise_type_is_valid(fType) && 252 buffer.validate(perlin_noise_type_is_valid(fType) &&
310 (fNumOctaves >= 0) && (fNumOctaves <= 255)); 253 (fNumOctaves >= 0) && (fNumOctaves <= 255) &&
311 } 254 (fStitchTiles != fTileSize.isEmpty()));
312
313 SkPerlinNoiseShader::~SkPerlinNoiseShader() {
314 // Safety, should have been done in endContext()
315 SkDELETE(fPaintingData);
316 } 255 }
317 256
318 void SkPerlinNoiseShader::flatten(SkWriteBuffer& buffer) const { 257 void SkPerlinNoiseShader::flatten(SkWriteBuffer& buffer) const {
319 this->INHERITED::flatten(buffer); 258 this->INHERITED::flatten(buffer);
320 buffer.writeInt((int) fType); 259 buffer.writeInt((int) fType);
321 buffer.writeScalar(fBaseFrequencyX); 260 buffer.writePoint(fBaseFrequency);
322 buffer.writeScalar(fBaseFrequencyY);
323 buffer.writeInt(fNumOctaves); 261 buffer.writeInt(fNumOctaves);
324 buffer.writeScalar(fSeed); 262 buffer.writeInt(fSeed);
325 buffer.writeBool(fStitchTiles); 263 buffer.writeBool(fStitchTiles);
326 buffer.writeInt(fTileSize.fWidth); 264 buffer.writeInt(fTileSize.fWidth);
327 buffer.writeInt(fTileSize.fHeight); 265 buffer.writeInt(fTileSize.fHeight);
328 } 266 }
329 267
330 void SkPerlinNoiseShader::initPaint(PaintingData& paintingData) 268 SkScalar SkPerlinNoiseShader::noise2D(int channel, const StitchData& stitchData,
331 { 269 const SkPoint& noiseVector) const {
332 paintingData.init(fSeed);
333
334 // Set frequencies to original values
335 paintingData.fBaseFrequency.set(fBaseFrequencyX, fBaseFrequencyY);
336 // Adjust frequecies based on size if stitching is enabled
337 if (fStitchTiles) {
338 paintingData.stitch();
339 }
340 }
341
342 void SkPerlinNoiseShader::setTileSize(const SkISize& tileSize) {
343 fTileSize = tileSize;
344
345 if (NULL == fPaintingData) {
346 fPaintingData = SkNEW_ARGS(PaintingData, (fTileSize));
347 initPaint(*fPaintingData);
348 } else {
349 // Set Size
350 fPaintingData->fTileSize = fTileSize;
351 // Set frequencies to original values
352 fPaintingData->fBaseFrequency.set(fBaseFrequencyX, fBaseFrequencyY);
353 // Adjust frequecies based on size if stitching is enabled
354 if (fStitchTiles) {
355 fPaintingData->stitch();
356 }
357 }
358 }
359
360 SkScalar SkPerlinNoiseShader::noise2D(int channel, const PaintingData& paintingD ata,
361 const StitchData& stitchData, const SkPoint & noiseVector)
362 {
363 struct Noise { 270 struct Noise {
364 int noisePositionIntegerValue; 271 int noisePositionIntegerValue;
365 SkScalar noisePositionFractionValue; 272 SkScalar noisePositionFractionValue;
366 Noise(SkScalar component) 273 Noise(SkScalar component)
367 { 274 {
368 SkScalar position = component + kPerlinNoise; 275 SkScalar position = component + kPerlinNoise;
369 noisePositionIntegerValue = SkScalarFloorToInt(position); 276 noisePositionIntegerValue = SkScalarFloorToInt(position);
370 noisePositionFractionValue = position - SkIntToScalar(noisePositionI ntegerValue); 277 noisePositionFractionValue = position - SkIntToScalar(noisePositionI ntegerValue);
371 } 278 }
372 }; 279 };
373 Noise noiseX(noiseVector.x()); 280 Noise noiseX(noiseVector.x());
374 Noise noiseY(noiseVector.y()); 281 Noise noiseY(noiseVector.y());
375 SkScalar u, v; 282 SkScalar u, v;
376 // If stitching, adjust lattice points accordingly. 283 // If stitching, adjust lattice points accordingly.
377 if (fStitchTiles) { 284 if (fStitchTiles) {
378 noiseX.noisePositionIntegerValue = 285 noiseX.noisePositionIntegerValue =
379 checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stit chData.fWidth); 286 checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stit chData.fWidth);
380 noiseY.noisePositionIntegerValue = 287 noiseY.noisePositionIntegerValue =
381 checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stit chData.fHeight); 288 checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stit chData.fHeight);
382 } 289 }
383 noiseX.noisePositionIntegerValue &= kBlockMask; 290 noiseX.noisePositionIntegerValue &= kBlockMask;
384 noiseY.noisePositionIntegerValue &= kBlockMask; 291 noiseY.noisePositionIntegerValue &= kBlockMask;
385 int latticeIndex = 292 int latticeIndex = fLatticeSelector[noiseX.noisePositionIntegerValue] +
386 paintingData.fLatticeSelector[noiseX.noisePositionIntegerValue] + 293 noiseY.noisePositionIntegerValue;
387 noiseY.noisePositionIntegerValue; 294 int nextLatticeIndex = fLatticeSelector[(noiseX.noisePositionIntegerValue + 1) & kBlockMask] +
388 int nextLatticeIndex = 295 noiseY.noisePositionIntegerValue;
389 paintingData.fLatticeSelector[(noiseX.noisePositionIntegerValue + 1) & k BlockMask] +
390 noiseY.noisePositionIntegerValue;
391 SkScalar sx = smoothCurve(noiseX.noisePositionFractionValue); 296 SkScalar sx = smoothCurve(noiseX.noisePositionFractionValue);
392 SkScalar sy = smoothCurve(noiseY.noisePositionFractionValue); 297 SkScalar sy = smoothCurve(noiseY.noisePositionFractionValue);
393 // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html# feTurbulenceElement 298 // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html# feTurbulenceElement
394 SkPoint fractionValue = SkPoint::Make(noiseX.noisePositionFractionValue, 299 SkPoint fractionValue = SkPoint::Make(noiseX.noisePositionFractionValue,
395 noiseY.noisePositionFractionValue); // Offset (0,0) 300 noiseY.noisePositionFractionValue); // Offset (0,0)
396 u = paintingData.fGradient[channel][latticeIndex & kBlockMask].dot(fractionV alue); 301 u = fGradient[channel][latticeIndex & kBlockMask].dot(fractionValue);
397 fractionValue.fX -= SK_Scalar1; // Offset (-1,0) 302 fractionValue.fX -= SK_Scalar1; // Offset (-1,0)
398 v = paintingData.fGradient[channel][nextLatticeIndex & kBlockMask].dot(fract ionValue); 303 v = fGradient[channel][nextLatticeIndex & kBlockMask].dot(fractionValue);
399 SkScalar a = SkScalarInterp(u, v, sx); 304 SkScalar a = SkScalarInterp(u, v, sx);
400 fractionValue.fY -= SK_Scalar1; // Offset (-1,-1) 305 fractionValue.fY -= SK_Scalar1; // Offset (-1,-1)
401 v = paintingData.fGradient[channel][(nextLatticeIndex + 1) & kBlockMask].dot (fractionValue); 306 v = fGradient[channel][(nextLatticeIndex + 1) & kBlockMask].dot(fractionValu e);
402 fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1) 307 fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1)
403 u = paintingData.fGradient[channel][(latticeIndex + 1) & kBlockMask].dot(fra ctionValue); 308 u = fGradient[channel][(latticeIndex + 1) & kBlockMask].dot(fractionValue);
404 SkScalar b = SkScalarInterp(u, v, sx); 309 SkScalar b = SkScalarInterp(u, v, sx);
405 return SkScalarInterp(a, b, sy); 310 return SkScalarInterp(a, b, sy);
406 } 311 }
407 312
408 SkScalar SkPerlinNoiseShader::calculateTurbulenceValueForPoint( 313 SkScalar SkPerlinNoiseShader::calculateTurbulenceValueForPoint(int channel, Stit chData& stitchData,
409 int channel, const PaintingData& paintingData, StitchData& stitchData, const SkPoint& point) 314 const SkPoint& po int) const {
410 {
411 if (fStitchTiles) { 315 if (fStitchTiles) {
412 // Set up TurbulenceInitial stitch values. 316 // Set up TurbulenceInitial stitch values.
413 stitchData = paintingData.fStitchDataInit; 317 stitchData = fStitchDataInit;
414 } 318 }
415 SkScalar turbulenceFunctionResult = 0; 319 SkScalar turbulenceFunctionResult = 0;
416 SkPoint noiseVector(SkPoint::Make(SkScalarMul(point.x(), paintingData.fBaseF requency.fX), 320 SkPoint noiseVector(SkPoint::Make(SkScalarMul(point.x(), fBaseFrequency.fX),
417 SkScalarMul(point.y(), paintingData.fBaseF requency.fY))); 321 SkScalarMul(point.y(), fBaseFrequency.fY)) );
418 SkScalar ratio = SK_Scalar1; 322 SkScalar ratio = SK_Scalar1;
419 for (int octave = 0; octave < fNumOctaves; ++octave) { 323 for (int octave = 0; octave < fNumOctaves; ++octave) {
420 SkScalar noise = noise2D(channel, paintingData, stitchData, noiseVector) ; 324 SkScalar noise = noise2D(channel, stitchData, noiseVector);
421 turbulenceFunctionResult += SkScalarDiv( 325 turbulenceFunctionResult += SkScalarDiv(
422 (fType == kFractalNoise_Type) ? noise : SkScalarAbs(noise), ratio); 326 (fType == kFractalNoise_Type) ? noise : SkScalarAbs(noise), ratio);
423 noiseVector.fX *= 2; 327 noiseVector.fX *= 2;
424 noiseVector.fY *= 2; 328 noiseVector.fY *= 2;
425 ratio *= 2; 329 ratio *= 2;
426 if (fStitchTiles) { 330 if (fStitchTiles) {
427 // Update stitch values 331 // Update stitch values
428 stitchData.fWidth *= 2; 332 stitchData.fWidth *= 2;
429 stitchData.fWrapX = stitchData.fWidth + kPerlinNoise; 333 stitchData.fWrapX = stitchData.fWidth + kPerlinNoise;
430 stitchData.fHeight *= 2; 334 stitchData.fHeight *= 2;
(...skipping 10 matching lines...) Expand all
441 345
442 if (channel == 3) { // Scale alpha by paint value 346 if (channel == 3) { // Scale alpha by paint value
443 turbulenceFunctionResult = SkScalarMul(turbulenceFunctionResult, 347 turbulenceFunctionResult = SkScalarMul(turbulenceFunctionResult,
444 SkScalarDiv(SkIntToScalar(getPaintAlpha()), SkIntToScalar(255))); 348 SkScalarDiv(SkIntToScalar(getPaintAlpha()), SkIntToScalar(255)));
445 } 349 }
446 350
447 // Clamp result 351 // Clamp result
448 return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1); 352 return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1);
449 } 353 }
450 354
451 SkPMColor SkPerlinNoiseShader::shade(const SkPoint& point, StitchData& stitchDat a) { 355 SkPMColor SkPerlinNoiseShader::shade(const SkPoint& point, StitchData& stitchDat a) const {
452 SkMatrix matrix = fMatrix; 356 SkMatrix matrix = fMatrix;
453 matrix.postConcat(getLocalMatrix()); 357 matrix.postConcat(getLocalMatrix());
454 SkMatrix invMatrix; 358 SkMatrix invMatrix;
455 if (!matrix.invert(&invMatrix)) { 359 if (!matrix.invert(&invMatrix)) {
456 invMatrix.reset(); 360 invMatrix.reset();
457 } else { 361 } else {
458 invMatrix.postConcat(invMatrix); // Square the matrix 362 invMatrix.postConcat(invMatrix); // Square the matrix
459 } 363 }
460 // This (1,1) translation is due to WebKit's 1 based coordinates for the noi se 364 // This (1,1) translation is due to WebKit's 1 based coordinates for the noi se
461 // (as opposed to 0 based, usually). The same adjustment is in the setData() function. 365 // (as opposed to 0 based, usually). The same adjustment is in the setData() function.
462 matrix.postTranslate(SK_Scalar1, SK_Scalar1); 366 matrix.postTranslate(SK_Scalar1, SK_Scalar1);
463 SkPoint newPoint; 367 SkPoint newPoint;
464 matrix.mapPoints(&newPoint, &point, 1); 368 matrix.mapPoints(&newPoint, &point, 1);
465 invMatrix.mapPoints(&newPoint, &newPoint, 1); 369 invMatrix.mapPoints(&newPoint, &newPoint, 1);
466 newPoint.fX = SkScalarRoundToScalar(newPoint.fX); 370 newPoint.fX = SkScalarRoundToScalar(newPoint.fX);
467 newPoint.fY = SkScalarRoundToScalar(newPoint.fY); 371 newPoint.fY = SkScalarRoundToScalar(newPoint.fY);
468 372
469 U8CPU rgba[4]; 373 U8CPU rgba[4];
470 for (int channel = 3; channel >= 0; --channel) { 374 for (int channel = 3; channel >= 0; --channel) {
471 rgba[channel] = SkScalarFloorToInt(255 * 375 rgba[channel] = SkScalarFloorToInt(255 *
472 calculateTurbulenceValueForPoint(channel, *fPaintingData, stitchData , newPoint)); 376 calculateTurbulenceValueForPoint(channel, stitchData, newPoint));
473 } 377 }
474 return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]); 378 return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]);
475 } 379 }
476 380
477 bool SkPerlinNoiseShader::setContext(const SkBitmap& device, const SkPaint& pain t, 381 bool SkPerlinNoiseShader::setContext(const SkBitmap& device, const SkPaint& pain t,
478 const SkMatrix& matrix) { 382 const SkMatrix& matrix) {
479 fMatrix = matrix; 383 fMatrix = matrix;
480 return INHERITED::setContext(device, paint, matrix); 384 return INHERITED::setContext(device, paint, matrix);
481 } 385 }
482 386
(...skipping 831 matching lines...) Expand 10 before | Expand all | Expand 10 after
1314 return cf->asNewEffect(context); 1218 return cf->asNewEffect(context);
1315 } 1219 }
1316 1220
1317 // Either we don't stitch tiles, either we have a valid tile size 1221 // Either we don't stitch tiles, either we have a valid tile size
1318 SkASSERT(!fStitchTiles || !fTileSize.isEmpty()); 1222 SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
1319 1223
1320 #ifdef SK_USE_SIMPLEX_NOISE 1224 #ifdef SK_USE_SIMPLEX_NOISE
1321 // Simplex noise is currently disabled but can be enabled by defining SK_USE _SIMPLEX_NOISE 1225 // Simplex noise is currently disabled but can be enabled by defining SK_USE _SIMPLEX_NOISE
1322 sk_ignore_unused_variable(context); 1226 sk_ignore_unused_variable(context);
1323 GrEffectRef* effect = 1227 GrEffectRef* effect =
1324 GrSimplexNoiseEffect::Create(fType, fPaintingData->fBaseFrequency, 1228 GrSimplexNoiseEffect::Create(fType, fBaseFrequency,
1325 fNumOctaves, fStitchTiles, fSeed, 1229 fNumOctaves, fStitchTiles, fSeed,
1326 this->getLocalMatrix(), paint.getAlpha()); 1230 this->getLocalMatrix(), paint.getAlpha());
1327 #else 1231 #else
1328 GrTexture* permutationsTexture = GrLockAndRefCachedBitmapTexture( 1232 GrTexture* permutationsTexture = GrLockAndRefCachedBitmapTexture(
1329 context, *fPaintingData->getPermutationsBitmap(), NULL); 1233 context, this->getPermutationsBitmap(), NULL);
1330 GrTexture* noiseTexture = GrLockAndRefCachedBitmapTexture( 1234 GrTexture* noiseTexture = GrLockAndRefCachedBitmapTexture(
1331 context, *fPaintingData->getNoiseBitmap(), NULL); 1235 context, this->getNoiseBitmap(), NULL);
1332 1236
1333 GrEffectRef* effect = (NULL != permutationsTexture) && (NULL != noiseTexture ) ? 1237 GrEffectRef* effect = (NULL != permutationsTexture) && (NULL != noiseTexture ) ?
1334 GrPerlinNoiseEffect::Create(fType, fPaintingData->fBaseFrequency, 1238 GrPerlinNoiseEffect::Create(fType, fBaseFrequency,
1335 fNumOctaves, fStitchTiles, 1239 fNumOctaves, fStitchTiles,
1336 fPaintingData->fStitchDataInit, 1240 fStitchDataInit,
1337 permutationsTexture, noiseTexture, 1241 permutationsTexture, noiseTexture,
1338 this->getLocalMatrix(), paint.getAlpha()) : 1242 this->getLocalMatrix(), paint.getAlpha()) :
1339 NULL; 1243 NULL;
1340 1244
1341 // Unlock immediately, this is not great, but we don't have a way of 1245 // Unlock immediately, this is not great, but we don't have a way of
1342 // knowing when else to unlock it currently. TODO: Remove this when 1246 // knowing when else to unlock it currently. TODO: Remove this when
1343 // unref becomes the unlock replacement for all types of textures. 1247 // unref becomes the unlock replacement for all types of textures.
1344 if (NULL != permutationsTexture) { 1248 if (NULL != permutationsTexture) {
1345 GrUnlockAndUnrefCachedBitmapTexture(permutationsTexture); 1249 GrUnlockAndUnrefCachedBitmapTexture(permutationsTexture);
1346 } 1250 }
(...skipping 24 matching lines...) Expand all
1371 str->append("\"fractal noise\""); 1275 str->append("\"fractal noise\"");
1372 break; 1276 break;
1373 case kTurbulence_Type: 1277 case kTurbulence_Type:
1374 str->append("\"turbulence\""); 1278 str->append("\"turbulence\"");
1375 break; 1279 break;
1376 default: 1280 default:
1377 str->append("\"unknown\""); 1281 str->append("\"unknown\"");
1378 break; 1282 break;
1379 } 1283 }
1380 str->append(" base frequency: ("); 1284 str->append(" base frequency: (");
1381 str->appendScalar(fBaseFrequencyX); 1285 str->appendScalar(fBaseFrequency.fX);
1382 str->append(", "); 1286 str->append(", ");
1383 str->appendScalar(fBaseFrequencyY); 1287 str->appendScalar(fBaseFrequency.fY);
1384 str->append(") number of octaves: "); 1288 str->append(") number of octaves: ");
1385 str->appendS32(fNumOctaves); 1289 str->appendS32(fNumOctaves);
1386 str->append(" seed: "); 1290 str->append(" seed: ");
1387 str->appendScalar(fSeed); 1291 str->appendS32(fSeed);
1388 str->append(" stitch tiles: "); 1292 str->append(" stitch tiles: ");
1389 str->append(fStitchTiles ? "true " : "false "); 1293 str->append(fStitchTiles ? "true " : "false ");
1390 1294
1391 this->INHERITED::toString(str); 1295 this->INHERITED::toString(str);
1392 1296
1393 str->append(")"); 1297 str->append(")");
1394 } 1298 }
1395 #endif 1299 #endif
OLDNEW
« include/effects/SkPerlinNoiseShader.h ('K') | « include/effects/SkPerlinNoiseShader.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698