| Index: src/core/SkLightingShader.cpp
|
| diff --git a/src/core/SkLightingShader.cpp b/src/core/SkLightingShader.cpp
|
| index ca1c3417b4581ab5c404654e6acc4bd51bd8858c..52b208f8df6f2ff848513f8ea1cedc246c7c7bea 100644
|
| --- a/src/core/SkLightingShader.cpp
|
| +++ b/src/core/SkLightingShader.cpp
|
| @@ -12,6 +12,7 @@
|
| #include "SkErrorInternals.h"
|
| #include "SkLightingShader.h"
|
| #include "SkMathPriv.h"
|
| +#include "SkNormalSource.h"
|
| #include "SkPoint3.h"
|
| #include "SkReadBuffer.h"
|
| #include "SkWriteBuffer.h"
|
| @@ -55,7 +56,7 @@ public:
|
| const sk_sp<SkLights> lights,
|
| const SkVector& invNormRotation,
|
| const SkMatrix* diffLocalM, const SkMatrix* normLocalM,
|
| - sk_sp<SkLightingShader::NormalSource> normalSource)
|
| + sk_sp<SkNormalSource> normalSource)
|
| : INHERITED(diffLocalM)
|
| , fDiffuseMap(diffuse)
|
| , fNormalMap(normal)
|
| @@ -88,7 +89,7 @@ public:
|
| // 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, SkBitmapProcState* normalState);
|
| + SkBitmapProcState* diffuseState, SkNormalSource::Provider*);
|
| ~LightingShaderContext() override;
|
|
|
| void shadeSpan(int x, int y, SkPMColor[], int count) override;
|
| @@ -96,9 +97,9 @@ public:
|
| uint32_t getFlags() const override { return fFlags; }
|
|
|
| private:
|
| - SkBitmapProcState* fDiffuseState;
|
| - SkBitmapProcState* fNormalState;
|
| - uint32_t fFlags;
|
| + SkBitmapProcState* fDiffuseState;
|
| + SkNormalSource::Provider* fNormalProvider;
|
| + uint32_t fFlags;
|
|
|
| typedef SkShader::Context INHERITED;
|
| };
|
| @@ -110,7 +111,6 @@ protected:
|
| 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 @@ private:
|
| SkMatrix fNormLocalMatrix;
|
| SkVector fInvNormRotation;
|
|
|
| - sk_sp<SkLightingShader::NormalSource> fNormalSource;
|
| + sk_sp<SkNormalSource> fNormalSource;
|
|
|
| friend class SkLightingShader;
|
|
|
| @@ -367,13 +367,11 @@ bool SkLightingShaderImpl::isOpaque() const {
|
| }
|
|
|
| SkLightingShaderImpl::LightingShaderContext::LightingShaderContext(
|
| - const SkLightingShaderImpl& shader,
|
| - const ContextRec& rec,
|
| - SkBitmapProcState* diffuseState,
|
| - SkBitmapProcState* normalState)
|
| + const SkLightingShaderImpl& shader, const ContextRec& rec, SkBitmapProcState* diffuseState,
|
| + SkNormalSource::Provider* normalProvider)
|
| : INHERITED(shader, rec)
|
| , fDiffuseState(diffuseState)
|
| - , fNormalState(normalState) {
|
| + , fNormalProvider(normalProvider) {
|
| const SkPixmap& pixmap = fDiffuseState->fPixmap;
|
| bool isOpaque = pixmap.isOpaque();
|
|
|
| @@ -390,7 +388,7 @@ SkLightingShaderImpl::LightingShaderContext::~LightingShaderContext() {
|
| // 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();
|
| - fNormalState->~SkBitmapProcState();
|
| + fNormalProvider->~Provider();
|
| }
|
|
|
| static inline SkPMColor convert(SkColor3f color, U8CPU a) {
|
| @@ -417,29 +415,24 @@ static inline SkPMColor convert(SkColor3f color, U8CPU a) {
|
|
|
| // 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 TMP_COUNT 16
|
| +#define BUFFER_MAX ((int)(TMP_COUNT * sizeof(uint32_t)))
|
| 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], tmpNormal[TMP_COUNT];
|
| - SkPMColor tmpColor2[2*TMP_COUNT], tmpNormal2[2*TMP_COUNT];
|
| + uint32_t tmpColor[TMP_COUNT];
|
| + SkPMColor tmpColor2[2*TMP_COUNT];
|
|
|
| SkBitmapProcState::MatrixProc diffMProc = fDiffuseState->getMatrixProc();
|
| SkBitmapProcState::SampleProc32 diffSProc = fDiffuseState->getSampleProc32();
|
|
|
| - 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);
|
| + int max = fDiffuseState->maxCountForBufferSize(BUFFER_MAX);
|
|
|
| SkASSERT(fDiffuseState->fPixmap.addr());
|
| - SkASSERT(fNormalState->fPixmap.addr());
|
|
|
| - SkPoint3 norm, xformedNorm;
|
| + SkASSERT(max <= BUFFER_MAX);
|
| + SkPoint3 normals[BUFFER_MAX];
|
|
|
| do {
|
| int n = count;
|
| @@ -450,21 +443,9 @@ void SkLightingShaderImpl::LightingShaderContext::shadeSpan(int x, int y,
|
| diffMProc(*fDiffuseState, tmpColor, n, x, y);
|
| diffSProc(*fDiffuseState, tmpColor, n, tmpColor2);
|
|
|
| - normalMProc(*fNormalState, tmpNormal, n, x, y);
|
| - normalSProc(*fNormalState, tmpNormal, n, tmpNormal2);
|
| + fNormalProvider->fillScanLine(x, y, normals, n);
|
|
|
| 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]);
|
|
|
| @@ -476,7 +457,7 @@ void SkLightingShaderImpl::LightingShaderContext::shadeSpan(int x, int y,
|
| if (SkLights::Light::kAmbient_LightType == light.type()) {
|
| accum += light.color().makeScale(255.0f);
|
| } else {
|
| - SkScalar NdotL = xformedNorm.dot(light.dir());
|
| + SkScalar NdotL = normals[i].dot(light.dir());
|
| if (NdotL < 0.0f) {
|
| NdotL = 0.0f;
|
| }
|
| @@ -563,8 +544,7 @@ sk_sp<SkFlattenable> SkLightingShaderImpl::CreateProc(SkReadBuffer& buf) {
|
| invNormRotation = buf.readPoint();
|
| }
|
|
|
| - sk_sp<SkLightingShader::NormalSource> normalSource(
|
| - buf.readFlattenable<SkLightingShader::NormalSource>());
|
| + sk_sp<SkNormalSource> normalSource(buf.readFlattenable<SkNormalSource>());
|
|
|
| return sk_make_sp<SkLightingShaderImpl>(diffuse, normal, std::move(lights), invNormRotation,
|
| &diffLocalM, &normLocalM, std::move(normalSource));
|
| @@ -599,21 +579,10 @@ void SkLightingShaderImpl::flatten(SkWriteBuffer& buf) const {
|
| buf.writeFlattenable(fNormalSource.get());
|
| }
|
|
|
| -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);
|
| +size_t SkLightingShaderImpl::onContextSize(const ContextRec& rec) const {
|
| + return sizeof(LightingShaderContext) +
|
| + sizeof(SkBitmapProcState) +
|
| + fNormalSource->providerSize(rec);
|
| }
|
|
|
| SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec,
|
| @@ -623,11 +592,6 @@ SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec,
|
| // 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,
|
| SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
|
| @@ -637,21 +601,18 @@ SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec,
|
| diffuseState->~SkBitmapProcState();
|
| return nullptr;
|
| }
|
| + void* normalProviderStorage = (char*)storage +
|
| + sizeof(LightingShaderContext) +
|
| + sizeof(SkBitmapProcState);
|
|
|
| - 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)) {
|
| + SkNormalSource::Provider* normalProvider = fNormalSource->asProvider(rec,
|
| + normalProviderStorage);
|
| + if (!normalProvider) {
|
| diffuseState->~SkBitmapProcState();
|
| - normalState->~SkBitmapProcState();
|
| return nullptr;
|
| }
|
|
|
| - return new (storage) LightingShaderContext(*this, rec, diffuseState, normalState);
|
| + return new (storage) LightingShaderContext(*this, rec, diffuseState, normalProvider);
|
| }
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
| @@ -668,8 +629,12 @@ sk_sp<SkShader> SkLightingShader::Make(const SkBitmap& diffuse, const SkBitmap&
|
| }
|
| SkASSERT(SkScalarNearlyEqual(invNormRotation.lengthSqd(), SK_Scalar1));
|
|
|
| - sk_sp<SkLightingShader::NormalSource> normalSource =
|
| - SkLightingShader::NormalSource::MakeMap(normal, invNormRotation, normLocalM);
|
| + // 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);
|
|
|
| return sk_make_sp<SkLightingShaderImpl>(diffuse, normal, std::move(lights),
|
| invNormRotation, diffLocalM, normLocalM, std::move(normalSource));
|
|
|