| Index: src/core/SkLightingShader.cpp
|
| diff --git a/src/core/SkLightingShader.cpp b/src/core/SkLightingShader.cpp
|
| index 52b208f8df6f2ff848513f8ea1cedc246c7c7bea..ca1c3417b4581ab5c404654e6acc4bd51bd8858c 100644
|
| --- a/src/core/SkLightingShader.cpp
|
| +++ b/src/core/SkLightingShader.cpp
|
| @@ -12,7 +12,6 @@
|
| #include "SkErrorInternals.h"
|
| #include "SkLightingShader.h"
|
| #include "SkMathPriv.h"
|
| -#include "SkNormalSource.h"
|
| #include "SkPoint3.h"
|
| #include "SkReadBuffer.h"
|
| #include "SkWriteBuffer.h"
|
| @@ -56,7 +55,7 @@
|
| const sk_sp<SkLights> lights,
|
| const SkVector& invNormRotation,
|
| const SkMatrix* diffLocalM, const SkMatrix* normLocalM,
|
| - sk_sp<SkNormalSource> normalSource)
|
| + sk_sp<SkLightingShader::NormalSource> normalSource)
|
| : INHERITED(diffLocalM)
|
| , fDiffuseMap(diffuse)
|
| , fNormalMap(normal)
|
| @@ -89,7 +88,7 @@
|
| // The context takes ownership of the states. It will call their destructors
|
| // but will NOT free the memory.
|
| LightingShaderContext(const SkLightingShaderImpl&, const ContextRec&,
|
| - SkBitmapProcState* diffuseState, SkNormalSource::Provider*);
|
| + SkBitmapProcState* diffuseState, SkBitmapProcState* normalState);
|
| ~LightingShaderContext() override;
|
|
|
| void shadeSpan(int x, int y, SkPMColor[], int count) override;
|
| @@ -97,9 +96,9 @@
|
| uint32_t getFlags() const override { return fFlags; }
|
|
|
| private:
|
| - SkBitmapProcState* fDiffuseState;
|
| - SkNormalSource::Provider* fNormalProvider;
|
| - uint32_t fFlags;
|
| + SkBitmapProcState* fDiffuseState;
|
| + SkBitmapProcState* fNormalState;
|
| + uint32_t fFlags;
|
|
|
| typedef SkShader::Context INHERITED;
|
| };
|
| @@ -111,6 +110,7 @@
|
| void flatten(SkWriteBuffer&) const override;
|
| size_t onContextSize(const ContextRec&) const override;
|
| Context* onCreateContext(const ContextRec&, void*) const override;
|
| + bool computeNormTotalInverse(const ContextRec& rec, SkMatrix* normTotalInverse) const;
|
|
|
| private:
|
| SkBitmap fDiffuseMap;
|
| @@ -121,7 +121,7 @@
|
| SkMatrix fNormLocalMatrix;
|
| SkVector fInvNormRotation;
|
|
|
| - sk_sp<SkNormalSource> fNormalSource;
|
| + sk_sp<SkLightingShader::NormalSource> fNormalSource;
|
|
|
| friend class SkLightingShader;
|
|
|
| @@ -367,11 +367,13 @@
|
| }
|
|
|
| SkLightingShaderImpl::LightingShaderContext::LightingShaderContext(
|
| - const SkLightingShaderImpl& shader, const ContextRec& rec, SkBitmapProcState* diffuseState,
|
| - SkNormalSource::Provider* normalProvider)
|
| + const SkLightingShaderImpl& shader,
|
| + const ContextRec& rec,
|
| + SkBitmapProcState* diffuseState,
|
| + SkBitmapProcState* normalState)
|
| : INHERITED(shader, rec)
|
| , fDiffuseState(diffuseState)
|
| - , fNormalProvider(normalProvider) {
|
| + , fNormalState(normalState) {
|
| const SkPixmap& pixmap = fDiffuseState->fPixmap;
|
| bool isOpaque = pixmap.isOpaque();
|
|
|
| @@ -388,7 +390,7 @@
|
| // The bitmap proc states have been created outside of the context on memory that will be freed
|
| // elsewhere. Call the destructors but leave the freeing of the memory to the caller.
|
| fDiffuseState->~SkBitmapProcState();
|
| - fNormalProvider->~Provider();
|
| + fNormalState->~SkBitmapProcState();
|
| }
|
|
|
| static inline SkPMColor convert(SkColor3f color, U8CPU a) {
|
| @@ -415,24 +417,29 @@
|
|
|
| // larger is better (fewer times we have to loop), but we shouldn't
|
| // take up too much stack-space (each one here costs 16 bytes)
|
| -#define TMP_COUNT 16
|
| -#define BUFFER_MAX ((int)(TMP_COUNT * sizeof(uint32_t)))
|
| +#define TMP_COUNT 16
|
| +
|
| void SkLightingShaderImpl::LightingShaderContext::shadeSpan(int x, int y,
|
| SkPMColor result[], int count) {
|
| const SkLightingShaderImpl& lightShader = static_cast<const SkLightingShaderImpl&>(fShader);
|
|
|
| - uint32_t tmpColor[TMP_COUNT];
|
| - SkPMColor tmpColor2[2*TMP_COUNT];
|
| + uint32_t tmpColor[TMP_COUNT], tmpNormal[TMP_COUNT];
|
| + SkPMColor tmpColor2[2*TMP_COUNT], tmpNormal2[2*TMP_COUNT];
|
|
|
| SkBitmapProcState::MatrixProc diffMProc = fDiffuseState->getMatrixProc();
|
| SkBitmapProcState::SampleProc32 diffSProc = fDiffuseState->getSampleProc32();
|
|
|
| - int max = fDiffuseState->maxCountForBufferSize(BUFFER_MAX);
|
| + SkBitmapProcState::MatrixProc normalMProc = fNormalState->getMatrixProc();
|
| + SkBitmapProcState::SampleProc32 normalSProc = fNormalState->getSampleProc32();
|
| +
|
| + int diffMax = fDiffuseState->maxCountForBufferSize(sizeof(tmpColor[0]) * TMP_COUNT);
|
| + int normMax = fNormalState->maxCountForBufferSize(sizeof(tmpNormal[0]) * TMP_COUNT);
|
| + int max = SkTMin(diffMax, normMax);
|
|
|
| SkASSERT(fDiffuseState->fPixmap.addr());
|
| -
|
| - SkASSERT(max <= BUFFER_MAX);
|
| - SkPoint3 normals[BUFFER_MAX];
|
| + SkASSERT(fNormalState->fPixmap.addr());
|
| +
|
| + SkPoint3 norm, xformedNorm;
|
|
|
| do {
|
| int n = count;
|
| @@ -443,9 +450,21 @@
|
| diffMProc(*fDiffuseState, tmpColor, n, x, y);
|
| diffSProc(*fDiffuseState, tmpColor, n, tmpColor2);
|
|
|
| - fNormalProvider->fillScanLine(x, y, normals, n);
|
| + normalMProc(*fNormalState, tmpNormal, n, x, y);
|
| + normalSProc(*fNormalState, tmpNormal, n, tmpNormal2);
|
|
|
| for (int i = 0; i < n; ++i) {
|
| + SkASSERT(0xFF == SkColorGetA(tmpNormal2[i])); // opaque -> unpremul
|
| + norm.set(SkIntToScalar(SkGetPackedR32(tmpNormal2[i]))-127.0f,
|
| + SkIntToScalar(SkGetPackedG32(tmpNormal2[i]))-127.0f,
|
| + SkIntToScalar(SkGetPackedB32(tmpNormal2[i]))-127.0f);
|
| + norm.normalize();
|
| +
|
| + xformedNorm.fX = lightShader.fInvNormRotation.fX * norm.fX +
|
| + lightShader.fInvNormRotation.fY * norm.fY;
|
| + xformedNorm.fY = -lightShader.fInvNormRotation.fY * norm.fX +
|
| + lightShader.fInvNormRotation.fX * norm.fY;
|
| + xformedNorm.fZ = norm.fZ;
|
|
|
| SkColor diffColor = SkUnPreMultiply::PMColorToColor(tmpColor2[i]);
|
|
|
| @@ -457,7 +476,7 @@
|
| if (SkLights::Light::kAmbient_LightType == light.type()) {
|
| accum += light.color().makeScale(255.0f);
|
| } else {
|
| - SkScalar NdotL = normals[i].dot(light.dir());
|
| + SkScalar NdotL = xformedNorm.dot(light.dir());
|
| if (NdotL < 0.0f) {
|
| NdotL = 0.0f;
|
| }
|
| @@ -544,7 +563,8 @@
|
| invNormRotation = buf.readPoint();
|
| }
|
|
|
| - sk_sp<SkNormalSource> normalSource(buf.readFlattenable<SkNormalSource>());
|
| + sk_sp<SkLightingShader::NormalSource> normalSource(
|
| + buf.readFlattenable<SkLightingShader::NormalSource>());
|
|
|
| return sk_make_sp<SkLightingShaderImpl>(diffuse, normal, std::move(lights), invNormRotation,
|
| &diffLocalM, &normLocalM, std::move(normalSource));
|
| @@ -579,10 +599,21 @@
|
| buf.writeFlattenable(fNormalSource.get());
|
| }
|
|
|
| -size_t SkLightingShaderImpl::onContextSize(const ContextRec& rec) const {
|
| - return sizeof(LightingShaderContext) +
|
| - sizeof(SkBitmapProcState) +
|
| - fNormalSource->providerSize(rec);
|
| +bool SkLightingShaderImpl::computeNormTotalInverse(const ContextRec& rec,
|
| + SkMatrix* normTotalInverse) const {
|
| + SkMatrix total;
|
| + total.setConcat(*rec.fMatrix, fNormLocalMatrix);
|
| +
|
| + const SkMatrix* m = &total;
|
| + if (rec.fLocalMatrix) {
|
| + total.setConcat(*m, *rec.fLocalMatrix);
|
| + m = &total;
|
| + }
|
| + return m->invert(normTotalInverse);
|
| +}
|
| +
|
| +size_t SkLightingShaderImpl::onContextSize(const ContextRec&) const {
|
| + return 2 * sizeof(SkBitmapProcState) + sizeof(LightingShaderContext);
|
| }
|
|
|
| SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec,
|
| @@ -591,6 +622,11 @@
|
| SkMatrix diffTotalInv;
|
| // computeTotalInverse was called in SkShader::createContext so we know it will succeed
|
| SkAssertResult(this->computeTotalInverse(rec, &diffTotalInv));
|
| +
|
| + SkMatrix normTotalInv;
|
| + if (!this->computeNormTotalInverse(rec, &normTotalInv)) {
|
| + return nullptr;
|
| + }
|
|
|
| void* diffuseStateStorage = (char*)storage + sizeof(LightingShaderContext);
|
| SkBitmapProcState* diffuseState = new (diffuseStateStorage) SkBitmapProcState(fDiffuseMap,
|
| @@ -601,18 +637,21 @@
|
| diffuseState->~SkBitmapProcState();
|
| return nullptr;
|
| }
|
| - void* normalProviderStorage = (char*)storage +
|
| - sizeof(LightingShaderContext) +
|
| - sizeof(SkBitmapProcState);
|
| -
|
| - SkNormalSource::Provider* normalProvider = fNormalSource->asProvider(rec,
|
| - normalProviderStorage);
|
| - if (!normalProvider) {
|
| +
|
| + void* normalStateStorage = (char*)storage +
|
| + sizeof(LightingShaderContext) +
|
| + sizeof(SkBitmapProcState);
|
| + SkBitmapProcState* normalState = new (normalStateStorage) SkBitmapProcState(fNormalMap,
|
| + SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
|
| + SkMipMap::DeduceTreatment(rec));
|
| + SkASSERT(normalState);
|
| + if (!normalState->setup(normTotalInv, *rec.fPaint)) {
|
| diffuseState->~SkBitmapProcState();
|
| - return nullptr;
|
| - }
|
| -
|
| - return new (storage) LightingShaderContext(*this, rec, diffuseState, normalProvider);
|
| + normalState->~SkBitmapProcState();
|
| + return nullptr;
|
| + }
|
| +
|
| + return new (storage) LightingShaderContext(*this, rec, diffuseState, normalState);
|
| }
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
| @@ -629,12 +668,8 @@
|
| }
|
| SkASSERT(SkScalarNearlyEqual(invNormRotation.lengthSqd(), SK_Scalar1));
|
|
|
| - // TODO: support other tile modes
|
| - sk_sp<SkShader> mapShader = SkMakeBitmapShader(normal, SkShader::kClamp_TileMode,
|
| - SkShader::kClamp_TileMode, normLocalM, nullptr);
|
| -
|
| - sk_sp<SkNormalSource> normalSource = SkNormalSource::MakeFromNormalMap(mapShader,
|
| - invNormRotation);
|
| + sk_sp<SkLightingShader::NormalSource> normalSource =
|
| + SkLightingShader::NormalSource::MakeMap(normal, invNormRotation, normLocalM);
|
|
|
| return sk_make_sp<SkLightingShaderImpl>(diffuse, normal, std::move(lights),
|
| invNormRotation, diffLocalM, normLocalM, std::move(normalSource));
|
|
|