Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 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 "SkBitmapProcShader.h" | 8 #include "SkBitmapProcShader.h" |
| 9 #include "SkBitmapProcState.h" | 9 #include "SkBitmapProcState.h" |
| 10 #include "SkColor.h" | 10 #include "SkColor.h" |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 81 const SkMatrix* localMatrix, | 81 const SkMatrix* localMatrix, |
| 82 SkFilterQuality, | 82 SkFilterQuality, |
| 83 SkSourceGammaTreatment) const override; | 83 SkSourceGammaTreatment) const override; |
| 84 #endif | 84 #endif |
| 85 | 85 |
| 86 class LightingShaderContext : public SkShader::Context { | 86 class LightingShaderContext : public SkShader::Context { |
| 87 public: | 87 public: |
| 88 // The context takes ownership of the states. It will call their destruc tors | 88 // The context takes ownership of the states. It will call their destruc tors |
| 89 // but will NOT free the memory. | 89 // but will NOT free the memory. |
| 90 LightingShaderContext(const SkLightingShaderImpl&, const ContextRec&, | 90 LightingShaderContext(const SkLightingShaderImpl&, const ContextRec&, |
| 91 SkBitmapProcState* diffuseState, SkBitmapProcState * normalState); | 91 SkBitmapProcState* diffuseState, |
| 92 SkLightingShader::NormalSource::Provider*); | |
| 92 ~LightingShaderContext() override; | 93 ~LightingShaderContext() override; |
| 93 | 94 |
| 94 void shadeSpan(int x, int y, SkPMColor[], int count) override; | 95 void shadeSpan(int x, int y, SkPMColor[], int count) override; |
| 95 | 96 |
| 96 uint32_t getFlags() const override { return fFlags; } | 97 uint32_t getFlags() const override { return fFlags; } |
| 97 | 98 |
| 98 private: | 99 private: |
| 99 SkBitmapProcState* fDiffuseState; | 100 SkBitmapProcState* fDiffuseState; |
| 100 SkBitmapProcState* fNormalState; | 101 SkLightingShader::NormalSource::Provider* fNormalProvider; |
| 101 uint32_t fFlags; | 102 uint32_t fFlags; |
| 102 | 103 |
| 103 typedef SkShader::Context INHERITED; | 104 typedef SkShader::Context INHERITED; |
| 104 }; | 105 }; |
| 105 | 106 |
| 106 SK_TO_STRING_OVERRIDE() | 107 SK_TO_STRING_OVERRIDE() |
| 107 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingShaderImpl) | 108 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingShaderImpl) |
| 108 | 109 |
| 109 protected: | 110 protected: |
| 110 void flatten(SkWriteBuffer&) const override; | 111 void flatten(SkWriteBuffer&) const override; |
| 111 size_t onContextSize(const ContextRec&) const override; | 112 size_t onContextSize(const ContextRec&) const override; |
| 112 Context* onCreateContext(const ContextRec&, void*) const override; | 113 Context* onCreateContext(const ContextRec&, void*) const override; |
| 113 bool computeNormTotalInverse(const ContextRec& rec, SkMatrix* normTotalInver se) const; | |
| 114 | 114 |
| 115 private: | 115 private: |
| 116 SkBitmap fDiffuseMap; | 116 SkBitmap fDiffuseMap; |
| 117 SkBitmap fNormalMap; | 117 SkBitmap fNormalMap; |
| 118 | 118 |
| 119 sk_sp<SkLights> fLights; | 119 sk_sp<SkLights> fLights; |
| 120 | 120 |
| 121 SkMatrix fNormLocalMatrix; | 121 SkMatrix fNormLocalMatrix; |
| 122 SkVector fInvNormRotation; | 122 SkVector fInvNormRotation; |
| 123 | 123 |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 360 | 360 |
| 361 #endif | 361 #endif |
| 362 | 362 |
| 363 //////////////////////////////////////////////////////////////////////////// | 363 //////////////////////////////////////////////////////////////////////////// |
| 364 | 364 |
| 365 bool SkLightingShaderImpl::isOpaque() const { | 365 bool SkLightingShaderImpl::isOpaque() const { |
| 366 return fDiffuseMap.isOpaque(); | 366 return fDiffuseMap.isOpaque(); |
| 367 } | 367 } |
| 368 | 368 |
| 369 SkLightingShaderImpl::LightingShaderContext::LightingShaderContext( | 369 SkLightingShaderImpl::LightingShaderContext::LightingShaderContext( |
| 370 const SkLighting ShaderImpl& shader, | 370 const SkLightingShaderImpl& shader, const ContextRec& rec, SkBitmapProcS tate* diffuseState, |
| 371 const ContextRec & rec, | 371 SkLightingShader::NormalSource::Provider* normalProvider) |
| 372 SkBitmapProcStat e* diffuseState, | |
| 373 SkBitmapProcStat e* normalState) | |
| 374 : INHERITED(shader, rec) | 372 : INHERITED(shader, rec) |
| 375 , fDiffuseState(diffuseState) | 373 , fDiffuseState(diffuseState) |
| 376 , fNormalState(normalState) { | 374 , fNormalProvider(normalProvider) { |
| 377 const SkPixmap& pixmap = fDiffuseState->fPixmap; | 375 const SkPixmap& pixmap = fDiffuseState->fPixmap; |
| 378 bool isOpaque = pixmap.isOpaque(); | 376 bool isOpaque = pixmap.isOpaque(); |
| 379 | 377 |
| 380 // update fFlags | 378 // update fFlags |
| 381 uint32_t flags = 0; | 379 uint32_t flags = 0; |
| 382 if (isOpaque && (255 == this->getPaintAlpha())) { | 380 if (isOpaque && (255 == this->getPaintAlpha())) { |
| 383 flags |= kOpaqueAlpha_Flag; | 381 flags |= kOpaqueAlpha_Flag; |
| 384 } | 382 } |
| 385 | 383 |
| 386 fFlags = flags; | 384 fFlags = flags; |
| 387 } | 385 } |
| 388 | 386 |
| 389 SkLightingShaderImpl::LightingShaderContext::~LightingShaderContext() { | 387 SkLightingShaderImpl::LightingShaderContext::~LightingShaderContext() { |
| 390 // The bitmap proc states have been created outside of the context on memory that will be freed | 388 // The bitmap proc states have been created outside of the context on memory that will be freed |
| 391 // elsewhere. Call the destructors but leave the freeing of the memory to th e caller. | 389 // elsewhere. Call the destructors but leave the freeing of the memory to th e caller. |
| 392 fDiffuseState->~SkBitmapProcState(); | 390 fDiffuseState->~SkBitmapProcState(); |
| 393 fNormalState->~SkBitmapProcState(); | 391 fNormalProvider->~Provider(); |
| 394 } | 392 } |
| 395 | 393 |
| 396 static inline SkPMColor convert(SkColor3f color, U8CPU a) { | 394 static inline SkPMColor convert(SkColor3f color, U8CPU a) { |
| 397 if (color.fX <= 0.0f) { | 395 if (color.fX <= 0.0f) { |
| 398 color.fX = 0.0f; | 396 color.fX = 0.0f; |
| 399 } else if (color.fX >= 255.0f) { | 397 } else if (color.fX >= 255.0f) { |
| 400 color.fX = 255.0f; | 398 color.fX = 255.0f; |
| 401 } | 399 } |
| 402 | 400 |
| 403 if (color.fY <= 0.0f) { | 401 if (color.fY <= 0.0f) { |
| 404 color.fY = 0.0f; | 402 color.fY = 0.0f; |
| 405 } else if (color.fY >= 255.0f) { | 403 } else if (color.fY >= 255.0f) { |
| 406 color.fY = 255.0f; | 404 color.fY = 255.0f; |
| 407 } | 405 } |
| 408 | 406 |
| 409 if (color.fZ <= 0.0f) { | 407 if (color.fZ <= 0.0f) { |
| 410 color.fZ = 0.0f; | 408 color.fZ = 0.0f; |
| 411 } else if (color.fZ >= 255.0f) { | 409 } else if (color.fZ >= 255.0f) { |
| 412 color.fZ = 255.0f; | 410 color.fZ = 255.0f; |
| 413 } | 411 } |
| 414 | 412 |
| 415 return SkPreMultiplyARGB(a, (int) color.fX, (int) color.fY, (int) color.fZ) ; | 413 return SkPreMultiplyARGB(a, (int) color.fX, (int) color.fY, (int) color.fZ) ; |
| 416 } | 414 } |
| 417 | 415 |
| 418 // larger is better (fewer times we have to loop), but we shouldn't | 416 // larger is better (fewer times we have to loop), but we shouldn't |
| 419 // take up too much stack-space (each one here costs 16 bytes) | 417 // take up too much stack-space (each one here costs 16 bytes) |
| 418 // TODO: these defines are redundant with the ones in SkLightingShader_NormalSou rce.cpp, will | |
| 419 // consolidate in a future CL when the source of diffuse colores is factored out | |
| 420 #define TMP_COUNT 16 | 420 #define TMP_COUNT 16 |
| 421 #define BUFFER_MAX (TMP_COUNT * sizeof(uint32_t)) | |
| 421 | 422 |
| 422 void SkLightingShaderImpl::LightingShaderContext::shadeSpan(int x, int y, | 423 void SkLightingShaderImpl::LightingShaderContext::shadeSpan(int x, int y, |
| 423 SkPMColor result[], int count) { | 424 SkPMColor result[], int count) { |
| 424 const SkLightingShaderImpl& lightShader = static_cast<const SkLightingShader Impl&>(fShader); | 425 const SkLightingShaderImpl& lightShader = static_cast<const SkLightingShader Impl&>(fShader); |
| 425 | 426 |
| 426 uint32_t tmpColor[TMP_COUNT], tmpNormal[TMP_COUNT]; | 427 uint32_t tmpColor[TMP_COUNT]; |
| 427 SkPMColor tmpColor2[2*TMP_COUNT], tmpNormal2[2*TMP_COUNT]; | 428 SkPMColor tmpColor2[2*TMP_COUNT]; |
| 428 | 429 |
| 429 SkBitmapProcState::MatrixProc diffMProc = fDiffuseState->getMatrixProc(); | 430 SkBitmapProcState::MatrixProc diffMProc = fDiffuseState->getMatrixProc(); |
| 430 SkBitmapProcState::SampleProc32 diffSProc = fDiffuseState->getSampleProc32() ; | 431 SkBitmapProcState::SampleProc32 diffSProc = fDiffuseState->getSampleProc32() ; |
| 431 | 432 |
| 432 SkBitmapProcState::MatrixProc normalMProc = fNormalState->getMatrixProc(); | 433 int diffMax = fDiffuseState->maxCountForBufferSize(BUFFER_MAX); |
| 433 SkBitmapProcState::SampleProc32 normalSProc = fNormalState->getSampleProc32( ); | 434 int normMax = fNormalProvider->maxCountForFillScanLine(TMP_COUNT); |
| 434 | 435 size_t max = SkTMin(diffMax, normMax); |
| 435 int diffMax = fDiffuseState->maxCountForBufferSize(sizeof(tmpColor[0]) * TMP _COUNT); | |
| 436 int normMax = fNormalState->maxCountForBufferSize(sizeof(tmpNormal[0]) * TMP _COUNT); | |
| 437 int max = SkTMin(diffMax, normMax); | |
| 438 | 436 |
| 439 SkASSERT(fDiffuseState->fPixmap.addr()); | 437 SkASSERT(fDiffuseState->fPixmap.addr()); |
| 440 SkASSERT(fNormalState->fPixmap.addr()); | |
| 441 | 438 |
| 442 SkPoint3 norm, xformedNorm; | 439 SkASSERT(max <= BUFFER_MAX); |
| 440 SkPoint3 normals[BUFFER_MAX]; | |
| 443 | 441 |
| 444 do { | 442 do { |
| 445 int n = count; | 443 size_t n = count; |
|
egdaniel
2016/06/16 13:48:10
why the change to size_t here? Quick scan seems to
dvonbeck
2016/06/16 22:05:40
I was avoiding a compiler error "comparison betwee
| |
| 446 if (n > max) { | 444 if (n > max) { |
| 447 n = max; | 445 n = max; |
| 448 } | 446 } |
| 449 | 447 |
| 450 diffMProc(*fDiffuseState, tmpColor, n, x, y); | 448 diffMProc(*fDiffuseState, tmpColor, n, x, y); |
| 451 diffSProc(*fDiffuseState, tmpColor, n, tmpColor2); | 449 diffSProc(*fDiffuseState, tmpColor, n, tmpColor2); |
| 452 | 450 |
| 453 normalMProc(*fNormalState, tmpNormal, n, x, y); | 451 fNormalProvider->fillScanLine(x, y, normals, n); |
| 454 normalSProc(*fNormalState, tmpNormal, n, tmpNormal2); | |
| 455 | 452 |
| 456 for (int i = 0; i < n; ++i) { | 453 for (size_t i = 0; i < n; ++i) { |
| 457 SkASSERT(0xFF == SkColorGetA(tmpNormal2[i])); // opaque -> unpremul | |
| 458 norm.set(SkIntToScalar(SkGetPackedR32(tmpNormal2[i]))-127.0f, | |
| 459 SkIntToScalar(SkGetPackedG32(tmpNormal2[i]))-127.0f, | |
| 460 SkIntToScalar(SkGetPackedB32(tmpNormal2[i]))-127.0f); | |
| 461 norm.normalize(); | |
| 462 | |
| 463 xformedNorm.fX = lightShader.fInvNormRotation.fX * norm.fX + | |
| 464 lightShader.fInvNormRotation.fY * norm.fY; | |
| 465 xformedNorm.fY = -lightShader.fInvNormRotation.fY * norm.fX + | |
| 466 lightShader.fInvNormRotation.fX * norm.fY; | |
| 467 xformedNorm.fZ = norm.fZ; | |
| 468 | 454 |
| 469 SkColor diffColor = SkUnPreMultiply::PMColorToColor(tmpColor2[i]); | 455 SkColor diffColor = SkUnPreMultiply::PMColorToColor(tmpColor2[i]); |
| 470 | 456 |
| 471 SkColor3f accum = SkColor3f::Make(0.0f, 0.0f, 0.0f); | 457 SkColor3f accum = SkColor3f::Make(0.0f, 0.0f, 0.0f); |
| 472 // This is all done in linear unpremul color space (each component 0 ..255.0f though) | 458 // This is all done in linear unpremul color space (each component 0 ..255.0f though) |
| 473 for (int l = 0; l < lightShader.fLights->numLights(); ++l) { | 459 for (int l = 0; l < lightShader.fLights->numLights(); ++l) { |
| 474 const SkLights::Light& light = lightShader.fLights->light(l); | 460 const SkLights::Light& light = lightShader.fLights->light(l); |
| 475 | 461 |
| 476 if (SkLights::Light::kAmbient_LightType == light.type()) { | 462 if (SkLights::Light::kAmbient_LightType == light.type()) { |
| 477 accum += light.color().makeScale(255.0f); | 463 accum += light.color().makeScale(255.0f); |
| 478 } else { | 464 } else { |
| 479 SkScalar NdotL = xformedNorm.dot(light.dir()); | 465 SkScalar NdotL = normals[i].dot(light.dir()); |
| 480 if (NdotL < 0.0f) { | 466 if (NdotL < 0.0f) { |
| 481 NdotL = 0.0f; | 467 NdotL = 0.0f; |
| 482 } | 468 } |
| 483 | 469 |
| 484 accum.fX += light.color().fX * SkColorGetR(diffColor) * Ndot L; | 470 accum.fX += light.color().fX * SkColorGetR(diffColor) * Ndot L; |
| 485 accum.fY += light.color().fY * SkColorGetG(diffColor) * Ndot L; | 471 accum.fY += light.color().fY * SkColorGetG(diffColor) * Ndot L; |
| 486 accum.fZ += light.color().fZ * SkColorGetB(diffColor) * Ndot L; | 472 accum.fZ += light.color().fZ * SkColorGetB(diffColor) * Ndot L; |
| 487 } | 473 } |
| 488 } | 474 } |
| 489 | 475 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 592 buf.writeScalarArray(&light.color().fX, 3); | 578 buf.writeScalarArray(&light.color().fX, 3); |
| 593 if (!isAmbient) { | 579 if (!isAmbient) { |
| 594 buf.writeScalarArray(&light.dir().fX, 3); | 580 buf.writeScalarArray(&light.dir().fX, 3); |
| 595 } | 581 } |
| 596 } | 582 } |
| 597 buf.writePoint(fInvNormRotation); | 583 buf.writePoint(fInvNormRotation); |
| 598 | 584 |
| 599 buf.writeFlattenable(fNormalSource.get()); | 585 buf.writeFlattenable(fNormalSource.get()); |
| 600 } | 586 } |
| 601 | 587 |
| 602 bool SkLightingShaderImpl::computeNormTotalInverse(const ContextRec& rec, | |
| 603 SkMatrix* normTotalInverse) c onst { | |
| 604 SkMatrix total; | |
| 605 total.setConcat(*rec.fMatrix, fNormLocalMatrix); | |
| 606 | |
| 607 const SkMatrix* m = &total; | |
| 608 if (rec.fLocalMatrix) { | |
| 609 total.setConcat(*m, *rec.fLocalMatrix); | |
| 610 m = &total; | |
| 611 } | |
| 612 return m->invert(normTotalInverse); | |
| 613 } | |
| 614 | |
| 615 size_t SkLightingShaderImpl::onContextSize(const ContextRec&) const { | 588 size_t SkLightingShaderImpl::onContextSize(const ContextRec&) const { |
| 616 return 2 * sizeof(SkBitmapProcState) + sizeof(LightingShaderContext); | 589 return sizeof(LightingShaderContext) + |
| 590 sizeof(SkBitmapProcState) + | |
| 591 fNormalSource->providerSize(); | |
| 617 } | 592 } |
| 618 | 593 |
| 619 SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec, | 594 SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec, |
| 620 void* storage) const { | 595 void* storage) const { |
| 621 | 596 |
| 622 SkMatrix diffTotalInv; | 597 SkMatrix diffTotalInv; |
| 623 // computeTotalInverse was called in SkShader::createContext so we know it w ill succeed | 598 // computeTotalInverse was called in SkShader::createContext so we know it w ill succeed |
| 624 SkAssertResult(this->computeTotalInverse(rec, &diffTotalInv)); | 599 SkAssertResult(this->computeTotalInverse(rec, &diffTotalInv)); |
| 625 | 600 |
| 626 SkMatrix normTotalInv; | |
| 627 if (!this->computeNormTotalInverse(rec, &normTotalInv)) { | |
| 628 return nullptr; | |
| 629 } | |
| 630 | |
| 631 void* diffuseStateStorage = (char*)storage + sizeof(LightingShaderContext); | 601 void* diffuseStateStorage = (char*)storage + sizeof(LightingShaderContext); |
| 632 SkBitmapProcState* diffuseState = new (diffuseStateStorage) SkBitmapProcStat e(fDiffuseMap, | 602 SkBitmapProcState* diffuseState = new (diffuseStateStorage) SkBitmapProcStat e(fDiffuseMap, |
| 633 SkShader::kClamp_TileMode, SkShade r::kClamp_TileMode, | 603 SkShader::kClamp_TileMode, SkShade r::kClamp_TileMode, |
| 634 SkMipMap::De duceTreatment(rec)); | 604 SkMipMap::De duceTreatment(rec)); |
| 635 SkASSERT(diffuseState); | 605 SkASSERT(diffuseState); |
| 636 if (!diffuseState->setup(diffTotalInv, *rec.fPaint)) { | 606 if (!diffuseState->setup(diffTotalInv, *rec.fPaint)) { |
| 637 diffuseState->~SkBitmapProcState(); | 607 diffuseState->~SkBitmapProcState(); |
| 638 return nullptr; | 608 return nullptr; |
| 639 } | 609 } |
| 610 void* normalProviderStorage = (char*)storage + | |
| 611 sizeof(LightingShaderContext) + | |
| 612 sizeof(SkBitmapProcState); | |
| 613 | |
| 614 SkLightingShader::NormalSource::Provider* normalProvider = | |
| 615 fNormalSource->asProvider(rec, normalProviderStorage); | |
| 616 if (!normalProvider) { | |
| 617 diffuseState->~SkBitmapProcState(); | |
| 618 return nullptr; | |
| 619 } | |
| 640 | 620 |
| 641 void* normalStateStorage = (char*)storage + | 621 return new (storage) LightingShaderContext(*this, rec, diffuseState, normalP rovider); |
| 642 sizeof(LightingShaderContext) + | |
| 643 sizeof(SkBitmapProcState); | |
| 644 SkBitmapProcState* normalState = new (normalStateStorage) SkBitmapProcState( fNormalMap, | |
| 645 SkShader::kClamp_TileMode, SkShader: :kClamp_TileMode, | |
| 646 SkMipMap::De duceTreatment(rec)); | |
| 647 SkASSERT(normalState); | |
| 648 if (!normalState->setup(normTotalInv, *rec.fPaint)) { | |
| 649 diffuseState->~SkBitmapProcState(); | |
| 650 normalState->~SkBitmapProcState(); | |
| 651 return nullptr; | |
| 652 } | |
| 653 | |
| 654 return new (storage) LightingShaderContext(*this, rec, diffuseState, normalS tate); | |
| 655 } | 622 } |
| 656 | 623 |
| 657 /////////////////////////////////////////////////////////////////////////////// | 624 /////////////////////////////////////////////////////////////////////////////// |
| 658 | 625 |
| 659 sk_sp<SkShader> SkLightingShader::Make(const SkBitmap& diffuse, const SkBitmap& normal, | 626 sk_sp<SkShader> SkLightingShader::Make(const SkBitmap& diffuse, const SkBitmap& normal, |
| 660 sk_sp<SkLights> lights, | 627 sk_sp<SkLights> lights, |
| 661 const SkVector& invNormRotation, | 628 const SkVector& invNormRotation, |
| 662 const SkMatrix* diffLocalM, const SkMatri x* normLocalM) { | 629 const SkMatrix* diffLocalM, const SkMatri x* normLocalM) { |
| 663 if (diffuse.isNull() || SkBitmapProcShader::BitmapIsTooBig(diffuse) || | 630 if (diffuse.isNull() || SkBitmapProcShader::BitmapIsTooBig(diffuse) || |
| 664 normal.isNull() || SkBitmapProcShader::BitmapIsTooBig(normal) || | 631 normal.isNull() || SkBitmapProcShader::BitmapIsTooBig(normal) || |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 675 invNormRotation, diffLocalM, normLocalM, std::move(normalSource)); | 642 invNormRotation, diffLocalM, normLocalM, std::move(normalSource)); |
| 676 } | 643 } |
| 677 | 644 |
| 678 /////////////////////////////////////////////////////////////////////////////// | 645 /////////////////////////////////////////////////////////////////////////////// |
| 679 | 646 |
| 680 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingShader) | 647 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingShader) |
| 681 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingShaderImpl) | 648 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingShaderImpl) |
| 682 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 649 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
| 683 | 650 |
| 684 /////////////////////////////////////////////////////////////////////////////// | 651 /////////////////////////////////////////////////////////////////////////////// |
| OLD | NEW |