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

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

Issue 207683004: Extract most of the mutable state of SkShader into a separate Context object. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: rebase Created 6 years, 8 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
« no previous file with comments | « src/core/SkSmallAllocator.h ('k') | src/effects/SkTransparentShader.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 const SkISize* tileSize) 271 const SkISize* tileSize)
272 : fType(type) 272 : fType(type)
273 , fBaseFrequencyX(baseFrequencyX) 273 , fBaseFrequencyX(baseFrequencyX)
274 , fBaseFrequencyY(baseFrequencyY) 274 , fBaseFrequencyY(baseFrequencyY)
275 , fNumOctaves(numOctaves > 255 ? 255 : numOctaves/*[0,255] octaves allowed*/) 275 , fNumOctaves(numOctaves > 255 ? 255 : numOctaves/*[0,255] octaves allowed*/)
276 , fSeed(seed) 276 , fSeed(seed)
277 , fTileSize(NULL == tileSize ? SkISize::Make(0, 0) : *tileSize) 277 , fTileSize(NULL == tileSize ? SkISize::Make(0, 0) : *tileSize)
278 , fStitchTiles(!fTileSize.isEmpty()) 278 , fStitchTiles(!fTileSize.isEmpty())
279 { 279 {
280 SkASSERT(numOctaves >= 0 && numOctaves < 256); 280 SkASSERT(numOctaves >= 0 && numOctaves < 256);
281 fMatrix.reset();
282 fPaintingData = SkNEW_ARGS(PaintingData, (fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY)); 281 fPaintingData = SkNEW_ARGS(PaintingData, (fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY));
283 } 282 }
284 283
285 SkPerlinNoiseShader::SkPerlinNoiseShader(SkReadBuffer& buffer) 284 SkPerlinNoiseShader::SkPerlinNoiseShader(SkReadBuffer& buffer)
286 : INHERITED(buffer) 285 : INHERITED(buffer)
287 { 286 {
288 fType = (SkPerlinNoiseShader::Type) buffer.readInt(); 287 fType = (SkPerlinNoiseShader::Type) buffer.readInt();
289 fBaseFrequencyX = buffer.readScalar(); 288 fBaseFrequencyX = buffer.readScalar();
290 fBaseFrequencyY = buffer.readScalar(); 289 fBaseFrequencyY = buffer.readScalar();
291 fNumOctaves = buffer.readInt(); 290 fNumOctaves = buffer.readInt();
292 fSeed = buffer.readScalar(); 291 fSeed = buffer.readScalar();
293 fStitchTiles = buffer.readBool(); 292 fStitchTiles = buffer.readBool();
294 fTileSize.fWidth = buffer.readInt(); 293 fTileSize.fWidth = buffer.readInt();
295 fTileSize.fHeight = buffer.readInt(); 294 fTileSize.fHeight = buffer.readInt();
296 fMatrix.reset();
297 fPaintingData = SkNEW_ARGS(PaintingData, (fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY)); 295 fPaintingData = SkNEW_ARGS(PaintingData, (fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY));
298 buffer.validate(perlin_noise_type_is_valid(fType) && 296 buffer.validate(perlin_noise_type_is_valid(fType) &&
299 (fNumOctaves >= 0) && (fNumOctaves <= 255) && 297 (fNumOctaves >= 0) && (fNumOctaves <= 255) &&
300 (fStitchTiles != fTileSize.isEmpty())); 298 (fStitchTiles != fTileSize.isEmpty()));
301 } 299 }
302 300
303 SkPerlinNoiseShader::~SkPerlinNoiseShader() { 301 SkPerlinNoiseShader::~SkPerlinNoiseShader() {
304 // Safety, should have been done in endContext() 302 // Safety, should have been done in endContext()
305 SkDELETE(fPaintingData); 303 SkDELETE(fPaintingData);
306 } 304 }
307 305
308 void SkPerlinNoiseShader::flatten(SkWriteBuffer& buffer) const { 306 void SkPerlinNoiseShader::flatten(SkWriteBuffer& buffer) const {
309 this->INHERITED::flatten(buffer); 307 this->INHERITED::flatten(buffer);
310 buffer.writeInt((int) fType); 308 buffer.writeInt((int) fType);
311 buffer.writeScalar(fBaseFrequencyX); 309 buffer.writeScalar(fBaseFrequencyX);
312 buffer.writeScalar(fBaseFrequencyY); 310 buffer.writeScalar(fBaseFrequencyY);
313 buffer.writeInt(fNumOctaves); 311 buffer.writeInt(fNumOctaves);
314 buffer.writeScalar(fSeed); 312 buffer.writeScalar(fSeed);
315 buffer.writeBool(fStitchTiles); 313 buffer.writeBool(fStitchTiles);
316 buffer.writeInt(fTileSize.fWidth); 314 buffer.writeInt(fTileSize.fWidth);
317 buffer.writeInt(fTileSize.fHeight); 315 buffer.writeInt(fTileSize.fHeight);
318 } 316 }
319 317
320 SkScalar SkPerlinNoiseShader::noise2D(int channel, const PaintingData& paintingD ata, 318 SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::noise2D(
321 const StitchData& stitchData, 319 int channel, const PaintingData& paintingData,
322 const SkPoint& noiseVector) const { 320 const StitchData& stitchData, const SkPoint& noiseVector) const {
323 struct Noise { 321 struct Noise {
324 int noisePositionIntegerValue; 322 int noisePositionIntegerValue;
325 SkScalar noisePositionFractionValue; 323 SkScalar noisePositionFractionValue;
326 Noise(SkScalar component) 324 Noise(SkScalar component)
327 { 325 {
328 SkScalar position = component + kPerlinNoise; 326 SkScalar position = component + kPerlinNoise;
329 noisePositionIntegerValue = SkScalarFloorToInt(position); 327 noisePositionIntegerValue = SkScalarFloorToInt(position);
330 noisePositionFractionValue = position - SkIntToScalar(noisePositionI ntegerValue); 328 noisePositionFractionValue = position - SkIntToScalar(noisePositionI ntegerValue);
331 } 329 }
332 }; 330 };
333 Noise noiseX(noiseVector.x()); 331 Noise noiseX(noiseVector.x());
334 Noise noiseY(noiseVector.y()); 332 Noise noiseY(noiseVector.y());
335 SkScalar u, v; 333 SkScalar u, v;
334 const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoi seShader&>(fShader);
336 // If stitching, adjust lattice points accordingly. 335 // If stitching, adjust lattice points accordingly.
337 if (fStitchTiles) { 336 if (perlinNoiseShader.fStitchTiles) {
338 noiseX.noisePositionIntegerValue = 337 noiseX.noisePositionIntegerValue =
339 checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stit chData.fWidth); 338 checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stit chData.fWidth);
340 noiseY.noisePositionIntegerValue = 339 noiseY.noisePositionIntegerValue =
341 checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stit chData.fHeight); 340 checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stit chData.fHeight);
342 } 341 }
343 noiseX.noisePositionIntegerValue &= kBlockMask; 342 noiseX.noisePositionIntegerValue &= kBlockMask;
344 noiseY.noisePositionIntegerValue &= kBlockMask; 343 noiseY.noisePositionIntegerValue &= kBlockMask;
345 int latticeIndex = 344 int latticeIndex =
346 paintingData.fLatticeSelector[noiseX.noisePositionIntegerValue] + 345 paintingData.fLatticeSelector[noiseX.noisePositionIntegerValue] +
347 noiseY.noisePositionIntegerValue; 346 noiseY.noisePositionIntegerValue;
(...skipping 10 matching lines...) Expand all
358 v = paintingData.fGradient[channel][nextLatticeIndex & kBlockMask].dot(fract ionValue); 357 v = paintingData.fGradient[channel][nextLatticeIndex & kBlockMask].dot(fract ionValue);
359 SkScalar a = SkScalarInterp(u, v, sx); 358 SkScalar a = SkScalarInterp(u, v, sx);
360 fractionValue.fY -= SK_Scalar1; // Offset (-1,-1) 359 fractionValue.fY -= SK_Scalar1; // Offset (-1,-1)
361 v = paintingData.fGradient[channel][(nextLatticeIndex + 1) & kBlockMask].dot (fractionValue); 360 v = paintingData.fGradient[channel][(nextLatticeIndex + 1) & kBlockMask].dot (fractionValue);
362 fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1) 361 fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1)
363 u = paintingData.fGradient[channel][(latticeIndex + 1) & kBlockMask].dot(fra ctionValue); 362 u = paintingData.fGradient[channel][(latticeIndex + 1) & kBlockMask].dot(fra ctionValue);
364 SkScalar b = SkScalarInterp(u, v, sx); 363 SkScalar b = SkScalarInterp(u, v, sx);
365 return SkScalarInterp(a, b, sy); 364 return SkScalarInterp(a, b, sy);
366 } 365 }
367 366
368 SkScalar SkPerlinNoiseShader::calculateTurbulenceValueForPoint(int channel, 367 SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::calculateTurbulenceValue ForPoint(
369 const PaintingDat a& paintingData, 368 int channel, const PaintingData& paintingData,
370 StitchData& stitc hData, 369 StitchData& stitchData, const SkPoint& point) const {
371 const SkPoint& po int) const { 370 const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoi seShader&>(fShader);
372 if (fStitchTiles) { 371 if (perlinNoiseShader.fStitchTiles) {
373 // Set up TurbulenceInitial stitch values. 372 // Set up TurbulenceInitial stitch values.
374 stitchData = paintingData.fStitchDataInit; 373 stitchData = paintingData.fStitchDataInit;
375 } 374 }
376 SkScalar turbulenceFunctionResult = 0; 375 SkScalar turbulenceFunctionResult = 0;
377 SkPoint noiseVector(SkPoint::Make(SkScalarMul(point.x(), paintingData.fBaseF requency.fX), 376 SkPoint noiseVector(SkPoint::Make(SkScalarMul(point.x(), paintingData.fBaseF requency.fX),
378 SkScalarMul(point.y(), paintingData.fBaseF requency.fY))); 377 SkScalarMul(point.y(), paintingData.fBaseF requency.fY)));
379 SkScalar ratio = SK_Scalar1; 378 SkScalar ratio = SK_Scalar1;
380 for (int octave = 0; octave < fNumOctaves; ++octave) { 379 for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) {
381 SkScalar noise = noise2D(channel, paintingData, stitchData, noiseVector) ; 380 SkScalar noise = noise2D(channel, paintingData, stitchData, noiseVector) ;
382 turbulenceFunctionResult += SkScalarDiv( 381 turbulenceFunctionResult += SkScalarDiv(
383 (fType == kFractalNoise_Type) ? noise : SkScalarAbs(noise), ratio); 382 (perlinNoiseShader.fType == kFractalNoise_Type) ? noise : SkScalarAb s(noise), ratio);
384 noiseVector.fX *= 2; 383 noiseVector.fX *= 2;
385 noiseVector.fY *= 2; 384 noiseVector.fY *= 2;
386 ratio *= 2; 385 ratio *= 2;
387 if (fStitchTiles) { 386 if (perlinNoiseShader.fStitchTiles) {
388 // Update stitch values 387 // Update stitch values
389 stitchData.fWidth *= 2; 388 stitchData.fWidth *= 2;
390 stitchData.fWrapX = stitchData.fWidth + kPerlinNoise; 389 stitchData.fWrapX = stitchData.fWidth + kPerlinNoise;
391 stitchData.fHeight *= 2; 390 stitchData.fHeight *= 2;
392 stitchData.fWrapY = stitchData.fHeight + kPerlinNoise; 391 stitchData.fWrapY = stitchData.fHeight + kPerlinNoise;
393 } 392 }
394 } 393 }
395 394
396 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResu lt) + 1) / 2 395 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResu lt) + 1) / 2
397 // by fractalNoise and (turbulenceFunctionResult) by turbulence. 396 // by fractalNoise and (turbulenceFunctionResult) by turbulence.
398 if (fType == kFractalNoise_Type) { 397 if (perlinNoiseShader.fType == kFractalNoise_Type) {
399 turbulenceFunctionResult = 398 turbulenceFunctionResult =
400 SkScalarMul(turbulenceFunctionResult, SK_ScalarHalf) + SK_ScalarHalf ; 399 SkScalarMul(turbulenceFunctionResult, SK_ScalarHalf) + SK_ScalarHalf ;
401 } 400 }
402 401
403 if (channel == 3) { // Scale alpha by paint value 402 if (channel == 3) { // Scale alpha by paint value
404 turbulenceFunctionResult = SkScalarMul(turbulenceFunctionResult, 403 turbulenceFunctionResult = SkScalarMul(turbulenceFunctionResult,
405 SkScalarDiv(SkIntToScalar(getPaintAlpha()), SkIntToScalar(255))); 404 SkScalarDiv(SkIntToScalar(getPaintAlpha()), SkIntToScalar(255)));
406 } 405 }
407 406
408 // Clamp result 407 // Clamp result
409 return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1); 408 return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1);
410 } 409 }
411 410
412 SkPMColor SkPerlinNoiseShader::shade(const SkPoint& point, StitchData& stitchDat a) const { 411 SkPMColor SkPerlinNoiseShader::PerlinNoiseShaderContext::shade(
412 const SkPoint& point, StitchData& stitchData) const {
413 const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoi seShader&>(fShader);
413 SkPoint newPoint; 414 SkPoint newPoint;
414 fMatrix.mapPoints(&newPoint, &point, 1); 415 fMatrix.mapPoints(&newPoint, &point, 1);
415 newPoint.fX = SkScalarRoundToScalar(newPoint.fX); 416 newPoint.fX = SkScalarRoundToScalar(newPoint.fX);
416 newPoint.fY = SkScalarRoundToScalar(newPoint.fY); 417 newPoint.fY = SkScalarRoundToScalar(newPoint.fY);
417 418
418 U8CPU rgba[4]; 419 U8CPU rgba[4];
419 for (int channel = 3; channel >= 0; --channel) { 420 for (int channel = 3; channel >= 0; --channel) {
420 rgba[channel] = SkScalarFloorToInt(255 * 421 rgba[channel] = SkScalarFloorToInt(255 *
421 calculateTurbulenceValueForPoint(channel, *fPaintingData, stitchData , newPoint)); 422 calculateTurbulenceValueForPoint(channel, *perlinNoiseShader.fPainti ngData,
423 stitchData, newPoint));
422 } 424 }
423 return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]); 425 return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]);
424 } 426 }
425 427
426 bool SkPerlinNoiseShader::setContext(const SkBitmap& device, const SkPaint& pain t, 428 SkShader::Context* SkPerlinNoiseShader::createContext(const SkBitmap& device, co nst SkPaint& paint,
427 const SkMatrix& matrix) { 429 const SkMatrix& matrix, vo id* storage) const {
430 if (!this->validContext(device, paint, matrix)) {
431 return NULL;
432 }
433
434 return SkNEW_PLACEMENT_ARGS(storage, PerlinNoiseShaderContext, (*this, devic e, paint, matrix));
435 }
436
437 size_t SkPerlinNoiseShader::contextSize() const {
438 return sizeof(PerlinNoiseShaderContext);
439 }
440
441 SkPerlinNoiseShader::PerlinNoiseShaderContext::PerlinNoiseShaderContext(
442 const SkPerlinNoiseShader& shader, const SkBitmap& device,
443 const SkPaint& paint, const SkMatrix& matrix)
444 : INHERITED(shader, device, paint, matrix)
445 {
428 SkMatrix newMatrix = matrix; 446 SkMatrix newMatrix = matrix;
429 newMatrix.postConcat(getLocalMatrix()); 447 newMatrix.postConcat(shader.getLocalMatrix());
430 SkMatrix invMatrix; 448 SkMatrix invMatrix;
431 if (!newMatrix.invert(&invMatrix)) { 449 if (!newMatrix.invert(&invMatrix)) {
432 invMatrix.reset(); 450 invMatrix.reset();
433 } 451 }
434 // This (1,1) translation is due to WebKit's 1 based coordinates for the noi se 452 // This (1,1) translation is due to WebKit's 1 based coordinates for the noi se
435 // (as opposed to 0 based, usually). The same adjustment is in the setData() function. 453 // (as opposed to 0 based, usually). The same adjustment is in the setData() function.
436 newMatrix.postTranslate(SK_Scalar1, SK_Scalar1); 454 newMatrix.postTranslate(SK_Scalar1, SK_Scalar1);
437 newMatrix.postConcat(invMatrix); 455 newMatrix.postConcat(invMatrix);
438 newMatrix.postConcat(invMatrix); 456 newMatrix.postConcat(invMatrix);
439 fMatrix = newMatrix; 457 fMatrix = newMatrix;
440 return INHERITED::setContext(device, paint, matrix);
441 } 458 }
442 459
443 void SkPerlinNoiseShader::shadeSpan(int x, int y, SkPMColor result[], int count) { 460 void SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan(
461 int x, int y, SkPMColor result[], int count) {
444 SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y)); 462 SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
445 StitchData stitchData; 463 StitchData stitchData;
446 for (int i = 0; i < count; ++i) { 464 for (int i = 0; i < count; ++i) {
447 result[i] = shade(point, stitchData); 465 result[i] = shade(point, stitchData);
448 point.fX += SK_Scalar1; 466 point.fX += SK_Scalar1;
449 } 467 }
450 } 468 }
451 469
452 void SkPerlinNoiseShader::shadeSpan16(int x, int y, uint16_t result[], int count ) { 470 void SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan16(
471 int x, int y, uint16_t result[], int count) {
453 SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y)); 472 SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
454 StitchData stitchData; 473 StitchData stitchData;
455 DITHER_565_SCAN(y); 474 DITHER_565_SCAN(y);
456 for (int i = 0; i < count; ++i) { 475 for (int i = 0; i < count; ++i) {
457 unsigned dither = DITHER_VALUE(x); 476 unsigned dither = DITHER_VALUE(x);
458 result[i] = SkDitherRGB32To565(shade(point, stitchData), dither); 477 result[i] = SkDitherRGB32To565(shade(point, stitchData), dither);
459 DITHER_INC_X(x); 478 DITHER_INC_X(x);
460 point.fX += SK_Scalar1; 479 point.fX += SK_Scalar1;
461 } 480 }
462 } 481 }
(...skipping 883 matching lines...) Expand 10 before | Expand all | Expand 10 after
1346 str->append(" seed: "); 1365 str->append(" seed: ");
1347 str->appendScalar(fSeed); 1366 str->appendScalar(fSeed);
1348 str->append(" stitch tiles: "); 1367 str->append(" stitch tiles: ");
1349 str->append(fStitchTiles ? "true " : "false "); 1368 str->append(fStitchTiles ? "true " : "false ");
1350 1369
1351 this->INHERITED::toString(str); 1370 this->INHERITED::toString(str);
1352 1371
1353 str->append(")"); 1372 str->append(")");
1354 } 1373 }
1355 #endif 1374 #endif
OLDNEW
« no previous file with comments | « src/core/SkSmallAllocator.h ('k') | src/effects/SkTransparentShader.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698