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