| 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" |
| 11 #include "SkEmptyShader.h" | 11 #include "SkEmptyShader.h" |
| 12 #include "SkErrorInternals.h" | 12 #include "SkErrorInternals.h" |
| 13 #include "SkLightingShader.h" | 13 #include "SkLightingShader.h" |
| 14 #include "SkMathPriv.h" | 14 #include "SkMathPriv.h" |
| 15 #include "SkNormalSource.h" | |
| 16 #include "SkPoint3.h" | 15 #include "SkPoint3.h" |
| 17 #include "SkReadBuffer.h" | 16 #include "SkReadBuffer.h" |
| 18 #include "SkWriteBuffer.h" | 17 #include "SkWriteBuffer.h" |
| 19 | 18 |
| 20 //////////////////////////////////////////////////////////////////////////// | 19 //////////////////////////////////////////////////////////////////////////// |
| 21 | 20 |
| 22 /* | 21 /* |
| 23 SkLightingShader TODOs: | 22 SkLightingShader TODOs: |
| 24 support other than clamp mode | 23 support other than clamp mode |
| 25 allow 'diffuse' & 'normal' to be of different dimensions? | 24 allow 'diffuse' & 'normal' to be of different dimensions? |
| (...skipping 23 matching lines...) Expand all Loading... |
| 49 @param lights the lights applied to the normal map | 48 @param lights the lights applied to the normal map |
| 50 @param invNormRotation rotation applied to the normal map's normals | 49 @param invNormRotation rotation applied to the normal map's normals |
| 51 @param diffLocalM the local matrix for the diffuse coordinates | 50 @param diffLocalM the local matrix for the diffuse coordinates |
| 52 @param normLocalM the local matrix for the normal coordinates | 51 @param normLocalM the local matrix for the normal coordinates |
| 53 @param normalSource the normal source for GPU computations | 52 @param normalSource the normal source for GPU computations |
| 54 */ | 53 */ |
| 55 SkLightingShaderImpl(const SkBitmap& diffuse, const SkBitmap& normal, | 54 SkLightingShaderImpl(const SkBitmap& diffuse, const SkBitmap& normal, |
| 56 const sk_sp<SkLights> lights, | 55 const sk_sp<SkLights> lights, |
| 57 const SkVector& invNormRotation, | 56 const SkVector& invNormRotation, |
| 58 const SkMatrix* diffLocalM, const SkMatrix* normLocalM, | 57 const SkMatrix* diffLocalM, const SkMatrix* normLocalM, |
| 59 sk_sp<SkNormalSource> normalSource) | 58 sk_sp<SkLightingShader::NormalSource> normalSource) |
| 60 : INHERITED(diffLocalM) | 59 : INHERITED(diffLocalM) |
| 61 , fDiffuseMap(diffuse) | 60 , fDiffuseMap(diffuse) |
| 62 , fNormalMap(normal) | 61 , fNormalMap(normal) |
| 63 , fLights(std::move(lights)) | 62 , fLights(std::move(lights)) |
| 64 , fInvNormRotation(invNormRotation) { | 63 , fInvNormRotation(invNormRotation) { |
| 65 | 64 |
| 66 if (normLocalM) { | 65 if (normLocalM) { |
| 67 fNormLocalMatrix = *normLocalM; | 66 fNormLocalMatrix = *normLocalM; |
| 68 } else { | 67 } else { |
| 69 fNormLocalMatrix.reset(); | 68 fNormLocalMatrix.reset(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 82 const SkMatrix* localMatrix, | 81 const SkMatrix* localMatrix, |
| 83 SkFilterQuality, | 82 SkFilterQuality, |
| 84 SkSourceGammaTreatment) const
override; | 83 SkSourceGammaTreatment) const
override; |
| 85 #endif | 84 #endif |
| 86 | 85 |
| 87 class LightingShaderContext : public SkShader::Context { | 86 class LightingShaderContext : public SkShader::Context { |
| 88 public: | 87 public: |
| 89 // 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 |
| 90 // but will NOT free the memory. | 89 // but will NOT free the memory. |
| 91 LightingShaderContext(const SkLightingShaderImpl&, const ContextRec&, | 90 LightingShaderContext(const SkLightingShaderImpl&, const ContextRec&, |
| 92 SkBitmapProcState* diffuseState, SkNormalSource::P
rovider*); | 91 SkBitmapProcState* diffuseState, SkBitmapProcState
* normalState); |
| 93 ~LightingShaderContext() override; | 92 ~LightingShaderContext() override; |
| 94 | 93 |
| 95 void shadeSpan(int x, int y, SkPMColor[], int count) override; | 94 void shadeSpan(int x, int y, SkPMColor[], int count) override; |
| 96 | 95 |
| 97 uint32_t getFlags() const override { return fFlags; } | 96 uint32_t getFlags() const override { return fFlags; } |
| 98 | 97 |
| 99 private: | 98 private: |
| 100 SkBitmapProcState* fDiffuseState; | 99 SkBitmapProcState* fDiffuseState; |
| 101 SkNormalSource::Provider* fNormalProvider; | 100 SkBitmapProcState* fNormalState; |
| 102 uint32_t fFlags; | 101 uint32_t fFlags; |
| 103 | 102 |
| 104 typedef SkShader::Context INHERITED; | 103 typedef SkShader::Context INHERITED; |
| 105 }; | 104 }; |
| 106 | 105 |
| 107 SK_TO_STRING_OVERRIDE() | 106 SK_TO_STRING_OVERRIDE() |
| 108 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingShaderImpl) | 107 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingShaderImpl) |
| 109 | 108 |
| 110 protected: | 109 protected: |
| 111 void flatten(SkWriteBuffer&) const override; | 110 void flatten(SkWriteBuffer&) const override; |
| 112 size_t onContextSize(const ContextRec&) const override; | 111 size_t onContextSize(const ContextRec&) const override; |
| 113 Context* onCreateContext(const ContextRec&, void*) const override; | 112 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 |
| 124 sk_sp<SkNormalSource> fNormalSource; | 124 sk_sp<SkLightingShader::NormalSource> fNormalSource; |
| 125 | 125 |
| 126 friend class SkLightingShader; | 126 friend class SkLightingShader; |
| 127 | 127 |
| 128 typedef SkShader INHERITED; | 128 typedef SkShader INHERITED; |
| 129 }; | 129 }; |
| 130 | 130 |
| 131 //////////////////////////////////////////////////////////////////////////// | 131 //////////////////////////////////////////////////////////////////////////// |
| 132 | 132 |
| 133 #if SK_SUPPORT_GPU | 133 #if SK_SUPPORT_GPU |
| 134 | 134 |
| (...skipping 225 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 SkLightingShaderImpl& shader, const ContextRec& rec, SkBitmapProcS
tate* diffuseState, | 370 const SkLighting
ShaderImpl& shader, |
| 371 SkNormalSource::Provider* normalProvider) | 371 const ContextRec
& rec, |
| 372 SkBitmapProcStat
e* diffuseState, |
| 373 SkBitmapProcStat
e* normalState) |
| 372 : INHERITED(shader, rec) | 374 : INHERITED(shader, rec) |
| 373 , fDiffuseState(diffuseState) | 375 , fDiffuseState(diffuseState) |
| 374 , fNormalProvider(normalProvider) { | 376 , fNormalState(normalState) { |
| 375 const SkPixmap& pixmap = fDiffuseState->fPixmap; | 377 const SkPixmap& pixmap = fDiffuseState->fPixmap; |
| 376 bool isOpaque = pixmap.isOpaque(); | 378 bool isOpaque = pixmap.isOpaque(); |
| 377 | 379 |
| 378 // update fFlags | 380 // update fFlags |
| 379 uint32_t flags = 0; | 381 uint32_t flags = 0; |
| 380 if (isOpaque && (255 == this->getPaintAlpha())) { | 382 if (isOpaque && (255 == this->getPaintAlpha())) { |
| 381 flags |= kOpaqueAlpha_Flag; | 383 flags |= kOpaqueAlpha_Flag; |
| 382 } | 384 } |
| 383 | 385 |
| 384 fFlags = flags; | 386 fFlags = flags; |
| 385 } | 387 } |
| 386 | 388 |
| 387 SkLightingShaderImpl::LightingShaderContext::~LightingShaderContext() { | 389 SkLightingShaderImpl::LightingShaderContext::~LightingShaderContext() { |
| 388 // The bitmap proc states have been created outside of the context on memory
that will be freed | 390 // The bitmap proc states have been created outside of the context on memory
that will be freed |
| 389 // elsewhere. Call the destructors but leave the freeing of the memory to th
e caller. | 391 // elsewhere. Call the destructors but leave the freeing of the memory to th
e caller. |
| 390 fDiffuseState->~SkBitmapProcState(); | 392 fDiffuseState->~SkBitmapProcState(); |
| 391 fNormalProvider->~Provider(); | 393 fNormalState->~SkBitmapProcState(); |
| 392 } | 394 } |
| 393 | 395 |
| 394 static inline SkPMColor convert(SkColor3f color, U8CPU a) { | 396 static inline SkPMColor convert(SkColor3f color, U8CPU a) { |
| 395 if (color.fX <= 0.0f) { | 397 if (color.fX <= 0.0f) { |
| 396 color.fX = 0.0f; | 398 color.fX = 0.0f; |
| 397 } else if (color.fX >= 255.0f) { | 399 } else if (color.fX >= 255.0f) { |
| 398 color.fX = 255.0f; | 400 color.fX = 255.0f; |
| 399 } | 401 } |
| 400 | 402 |
| 401 if (color.fY <= 0.0f) { | 403 if (color.fY <= 0.0f) { |
| 402 color.fY = 0.0f; | 404 color.fY = 0.0f; |
| 403 } else if (color.fY >= 255.0f) { | 405 } else if (color.fY >= 255.0f) { |
| 404 color.fY = 255.0f; | 406 color.fY = 255.0f; |
| 405 } | 407 } |
| 406 | 408 |
| 407 if (color.fZ <= 0.0f) { | 409 if (color.fZ <= 0.0f) { |
| 408 color.fZ = 0.0f; | 410 color.fZ = 0.0f; |
| 409 } else if (color.fZ >= 255.0f) { | 411 } else if (color.fZ >= 255.0f) { |
| 410 color.fZ = 255.0f; | 412 color.fZ = 255.0f; |
| 411 } | 413 } |
| 412 | 414 |
| 413 return SkPreMultiplyARGB(a, (int) color.fX, (int) color.fY, (int) color.fZ)
; | 415 return SkPreMultiplyARGB(a, (int) color.fX, (int) color.fY, (int) color.fZ)
; |
| 414 } | 416 } |
| 415 | 417 |
| 416 // larger is better (fewer times we have to loop), but we shouldn't | 418 // larger is better (fewer times we have to loop), but we shouldn't |
| 417 // take up too much stack-space (each one here costs 16 bytes) | 419 // take up too much stack-space (each one here costs 16 bytes) |
| 418 #define TMP_COUNT 16 | 420 #define TMP_COUNT 16 |
| 419 #define BUFFER_MAX ((int)(TMP_COUNT * sizeof(uint32_t))) | 421 |
| 420 void SkLightingShaderImpl::LightingShaderContext::shadeSpan(int x, int y, | 422 void SkLightingShaderImpl::LightingShaderContext::shadeSpan(int x, int y, |
| 421 SkPMColor result[],
int count) { | 423 SkPMColor result[],
int count) { |
| 422 const SkLightingShaderImpl& lightShader = static_cast<const SkLightingShader
Impl&>(fShader); | 424 const SkLightingShaderImpl& lightShader = static_cast<const SkLightingShader
Impl&>(fShader); |
| 423 | 425 |
| 424 uint32_t tmpColor[TMP_COUNT]; | 426 uint32_t tmpColor[TMP_COUNT], tmpNormal[TMP_COUNT]; |
| 425 SkPMColor tmpColor2[2*TMP_COUNT]; | 427 SkPMColor tmpColor2[2*TMP_COUNT], tmpNormal2[2*TMP_COUNT]; |
| 426 | 428 |
| 427 SkBitmapProcState::MatrixProc diffMProc = fDiffuseState->getMatrixProc(); | 429 SkBitmapProcState::MatrixProc diffMProc = fDiffuseState->getMatrixProc(); |
| 428 SkBitmapProcState::SampleProc32 diffSProc = fDiffuseState->getSampleProc32()
; | 430 SkBitmapProcState::SampleProc32 diffSProc = fDiffuseState->getSampleProc32()
; |
| 429 | 431 |
| 430 int max = fDiffuseState->maxCountForBufferSize(BUFFER_MAX); | 432 SkBitmapProcState::MatrixProc normalMProc = fNormalState->getMatrixProc(); |
| 433 SkBitmapProcState::SampleProc32 normalSProc = fNormalState->getSampleProc32(
); |
| 434 |
| 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); |
| 431 | 438 |
| 432 SkASSERT(fDiffuseState->fPixmap.addr()); | 439 SkASSERT(fDiffuseState->fPixmap.addr()); |
| 440 SkASSERT(fNormalState->fPixmap.addr()); |
| 433 | 441 |
| 434 SkASSERT(max <= BUFFER_MAX); | 442 SkPoint3 norm, xformedNorm; |
| 435 SkPoint3 normals[BUFFER_MAX]; | |
| 436 | 443 |
| 437 do { | 444 do { |
| 438 int n = count; | 445 int n = count; |
| 439 if (n > max) { | 446 if (n > max) { |
| 440 n = max; | 447 n = max; |
| 441 } | 448 } |
| 442 | 449 |
| 443 diffMProc(*fDiffuseState, tmpColor, n, x, y); | 450 diffMProc(*fDiffuseState, tmpColor, n, x, y); |
| 444 diffSProc(*fDiffuseState, tmpColor, n, tmpColor2); | 451 diffSProc(*fDiffuseState, tmpColor, n, tmpColor2); |
| 445 | 452 |
| 446 fNormalProvider->fillScanLine(x, y, normals, n); | 453 normalMProc(*fNormalState, tmpNormal, n, x, y); |
| 454 normalSProc(*fNormalState, tmpNormal, n, tmpNormal2); |
| 447 | 455 |
| 448 for (int i = 0; i < n; ++i) { | 456 for (int 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; |
| 449 | 468 |
| 450 SkColor diffColor = SkUnPreMultiply::PMColorToColor(tmpColor2[i]); | 469 SkColor diffColor = SkUnPreMultiply::PMColorToColor(tmpColor2[i]); |
| 451 | 470 |
| 452 SkColor3f accum = SkColor3f::Make(0.0f, 0.0f, 0.0f); | 471 SkColor3f accum = SkColor3f::Make(0.0f, 0.0f, 0.0f); |
| 453 // This is all done in linear unpremul color space (each component 0
..255.0f though) | 472 // This is all done in linear unpremul color space (each component 0
..255.0f though) |
| 454 for (int l = 0; l < lightShader.fLights->numLights(); ++l) { | 473 for (int l = 0; l < lightShader.fLights->numLights(); ++l) { |
| 455 const SkLights::Light& light = lightShader.fLights->light(l); | 474 const SkLights::Light& light = lightShader.fLights->light(l); |
| 456 | 475 |
| 457 if (SkLights::Light::kAmbient_LightType == light.type()) { | 476 if (SkLights::Light::kAmbient_LightType == light.type()) { |
| 458 accum += light.color().makeScale(255.0f); | 477 accum += light.color().makeScale(255.0f); |
| 459 } else { | 478 } else { |
| 460 SkScalar NdotL = normals[i].dot(light.dir()); | 479 SkScalar NdotL = xformedNorm.dot(light.dir()); |
| 461 if (NdotL < 0.0f) { | 480 if (NdotL < 0.0f) { |
| 462 NdotL = 0.0f; | 481 NdotL = 0.0f; |
| 463 } | 482 } |
| 464 | 483 |
| 465 accum.fX += light.color().fX * SkColorGetR(diffColor) * Ndot
L; | 484 accum.fX += light.color().fX * SkColorGetR(diffColor) * Ndot
L; |
| 466 accum.fY += light.color().fY * SkColorGetG(diffColor) * Ndot
L; | 485 accum.fY += light.color().fY * SkColorGetG(diffColor) * Ndot
L; |
| 467 accum.fZ += light.color().fZ * SkColorGetB(diffColor) * Ndot
L; | 486 accum.fZ += light.color().fZ * SkColorGetB(diffColor) * Ndot
L; |
| 468 } | 487 } |
| 469 } | 488 } |
| 470 | 489 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 537 } | 556 } |
| 538 } | 557 } |
| 539 | 558 |
| 540 sk_sp<SkLights> lights(builder.finish()); | 559 sk_sp<SkLights> lights(builder.finish()); |
| 541 | 560 |
| 542 SkVector invNormRotation = {1,0}; | 561 SkVector invNormRotation = {1,0}; |
| 543 if (!buf.isVersionLT(SkReadBuffer::kLightingShaderWritesInvNormRotation)) { | 562 if (!buf.isVersionLT(SkReadBuffer::kLightingShaderWritesInvNormRotation)) { |
| 544 invNormRotation = buf.readPoint(); | 563 invNormRotation = buf.readPoint(); |
| 545 } | 564 } |
| 546 | 565 |
| 547 sk_sp<SkNormalSource> normalSource(buf.readFlattenable<SkNormalSource>()); | 566 sk_sp<SkLightingShader::NormalSource> normalSource( |
| 567 buf.readFlattenable<SkLightingShader::NormalSource>()); |
| 548 | 568 |
| 549 return sk_make_sp<SkLightingShaderImpl>(diffuse, normal, std::move(lights),
invNormRotation, | 569 return sk_make_sp<SkLightingShaderImpl>(diffuse, normal, std::move(lights),
invNormRotation, |
| 550 &diffLocalM, &normLocalM, std::move(
normalSource)); | 570 &diffLocalM, &normLocalM, std::move(
normalSource)); |
| 551 } | 571 } |
| 552 | 572 |
| 553 void SkLightingShaderImpl::flatten(SkWriteBuffer& buf) const { | 573 void SkLightingShaderImpl::flatten(SkWriteBuffer& buf) const { |
| 554 this->INHERITED::flatten(buf); | 574 this->INHERITED::flatten(buf); |
| 555 | 575 |
| 556 bool hasNormLocalM = !fNormLocalMatrix.isIdentity(); | 576 bool hasNormLocalM = !fNormLocalMatrix.isIdentity(); |
| 557 buf.writeBool(hasNormLocalM); | 577 buf.writeBool(hasNormLocalM); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 572 buf.writeScalarArray(&light.color().fX, 3); | 592 buf.writeScalarArray(&light.color().fX, 3); |
| 573 if (!isAmbient) { | 593 if (!isAmbient) { |
| 574 buf.writeScalarArray(&light.dir().fX, 3); | 594 buf.writeScalarArray(&light.dir().fX, 3); |
| 575 } | 595 } |
| 576 } | 596 } |
| 577 buf.writePoint(fInvNormRotation); | 597 buf.writePoint(fInvNormRotation); |
| 578 | 598 |
| 579 buf.writeFlattenable(fNormalSource.get()); | 599 buf.writeFlattenable(fNormalSource.get()); |
| 580 } | 600 } |
| 581 | 601 |
| 582 size_t SkLightingShaderImpl::onContextSize(const ContextRec& rec) const { | 602 bool SkLightingShaderImpl::computeNormTotalInverse(const ContextRec& rec, |
| 583 return sizeof(LightingShaderContext) + | 603 SkMatrix* normTotalInverse) c
onst { |
| 584 sizeof(SkBitmapProcState) + | 604 SkMatrix total; |
| 585 fNormalSource->providerSize(rec); | 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 { |
| 616 return 2 * sizeof(SkBitmapProcState) + sizeof(LightingShaderContext); |
| 586 } | 617 } |
| 587 | 618 |
| 588 SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec, | 619 SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec, |
| 589 void* storage) const { | 620 void* storage) const { |
| 590 | 621 |
| 591 SkMatrix diffTotalInv; | 622 SkMatrix diffTotalInv; |
| 592 // computeTotalInverse was called in SkShader::createContext so we know it w
ill succeed | 623 // computeTotalInverse was called in SkShader::createContext so we know it w
ill succeed |
| 593 SkAssertResult(this->computeTotalInverse(rec, &diffTotalInv)); | 624 SkAssertResult(this->computeTotalInverse(rec, &diffTotalInv)); |
| 594 | 625 |
| 626 SkMatrix normTotalInv; |
| 627 if (!this->computeNormTotalInverse(rec, &normTotalInv)) { |
| 628 return nullptr; |
| 629 } |
| 630 |
| 595 void* diffuseStateStorage = (char*)storage + sizeof(LightingShaderContext); | 631 void* diffuseStateStorage = (char*)storage + sizeof(LightingShaderContext); |
| 596 SkBitmapProcState* diffuseState = new (diffuseStateStorage) SkBitmapProcStat
e(fDiffuseMap, | 632 SkBitmapProcState* diffuseState = new (diffuseStateStorage) SkBitmapProcStat
e(fDiffuseMap, |
| 597 SkShader::kClamp_TileMode, SkShade
r::kClamp_TileMode, | 633 SkShader::kClamp_TileMode, SkShade
r::kClamp_TileMode, |
| 598 SkMipMap::De
duceTreatment(rec)); | 634 SkMipMap::De
duceTreatment(rec)); |
| 599 SkASSERT(diffuseState); | 635 SkASSERT(diffuseState); |
| 600 if (!diffuseState->setup(diffTotalInv, *rec.fPaint)) { | 636 if (!diffuseState->setup(diffTotalInv, *rec.fPaint)) { |
| 601 diffuseState->~SkBitmapProcState(); | 637 diffuseState->~SkBitmapProcState(); |
| 602 return nullptr; | 638 return nullptr; |
| 603 } | 639 } |
| 604 void* normalProviderStorage = (char*)storage + | |
| 605 sizeof(LightingShaderContext) + | |
| 606 sizeof(SkBitmapProcState); | |
| 607 | |
| 608 SkNormalSource::Provider* normalProvider = fNormalSource->asProvider(rec, | |
| 609 normalP
roviderStorage); | |
| 610 if (!normalProvider) { | |
| 611 diffuseState->~SkBitmapProcState(); | |
| 612 return nullptr; | |
| 613 } | |
| 614 | 640 |
| 615 return new (storage) LightingShaderContext(*this, rec, diffuseState, normalP
rovider); | 641 void* normalStateStorage = (char*)storage + |
| 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); |
| 616 } | 655 } |
| 617 | 656 |
| 618 /////////////////////////////////////////////////////////////////////////////// | 657 /////////////////////////////////////////////////////////////////////////////// |
| 619 | 658 |
| 620 sk_sp<SkShader> SkLightingShader::Make(const SkBitmap& diffuse, const SkBitmap&
normal, | 659 sk_sp<SkShader> SkLightingShader::Make(const SkBitmap& diffuse, const SkBitmap&
normal, |
| 621 sk_sp<SkLights> lights, | 660 sk_sp<SkLights> lights, |
| 622 const SkVector& invNormRotation, | 661 const SkVector& invNormRotation, |
| 623 const SkMatrix* diffLocalM, const SkMatri
x* normLocalM) { | 662 const SkMatrix* diffLocalM, const SkMatri
x* normLocalM) { |
| 624 if (diffuse.isNull() || SkBitmapProcShader::BitmapIsTooBig(diffuse) || | 663 if (diffuse.isNull() || SkBitmapProcShader::BitmapIsTooBig(diffuse) || |
| 625 normal.isNull() || SkBitmapProcShader::BitmapIsTooBig(normal) || | 664 normal.isNull() || SkBitmapProcShader::BitmapIsTooBig(normal) || |
| 626 diffuse.width() != normal.width() || | 665 diffuse.width() != normal.width() || |
| 627 diffuse.height() != normal.height()) { | 666 diffuse.height() != normal.height()) { |
| 628 return nullptr; | 667 return nullptr; |
| 629 } | 668 } |
| 630 SkASSERT(SkScalarNearlyEqual(invNormRotation.lengthSqd(), SK_Scalar1)); | 669 SkASSERT(SkScalarNearlyEqual(invNormRotation.lengthSqd(), SK_Scalar1)); |
| 631 | 670 |
| 632 // TODO: support other tile modes | 671 sk_sp<SkLightingShader::NormalSource> normalSource = |
| 633 sk_sp<SkShader> mapShader = SkMakeBitmapShader(normal, SkShader::kClamp_Tile
Mode, | 672 SkLightingShader::NormalSource::MakeMap(normal, invNormRotation, nor
mLocalM); |
| 634 SkShader::kClamp_TileMode, no
rmLocalM, nullptr); | |
| 635 | |
| 636 sk_sp<SkNormalSource> normalSource = SkNormalSource::MakeFromNormalMap(mapSh
ader, | |
| 637 invNo
rmRotation); | |
| 638 | 673 |
| 639 return sk_make_sp<SkLightingShaderImpl>(diffuse, normal, std::move(lights), | 674 return sk_make_sp<SkLightingShaderImpl>(diffuse, normal, std::move(lights), |
| 640 invNormRotation, diffLocalM, normLocalM, std::move(normalSource)); | 675 invNormRotation, diffLocalM, normLocalM, std::move(normalSource)); |
| 641 } | 676 } |
| 642 | 677 |
| 643 /////////////////////////////////////////////////////////////////////////////// | 678 /////////////////////////////////////////////////////////////////////////////// |
| 644 | 679 |
| 645 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingShader) | 680 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingShader) |
| 646 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingShaderImpl) | 681 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingShaderImpl) |
| 647 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 682 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
| 648 | 683 |
| 649 /////////////////////////////////////////////////////////////////////////////// | 684 /////////////////////////////////////////////////////////////////////////////// |
| OLD | NEW |