Chromium Code Reviews| Index: src/core/SkLightingShader_NormalSource.cpp |
| diff --git a/src/core/SkLightingShader_NormalSource.cpp b/src/core/SkLightingShader_NormalSource.cpp |
| index 8ad3ed9ec57691811a0580574bbb9908831acda3..a09ff16f35fe2952487b84aa7549423178e97e52 100644 |
| --- a/src/core/SkLightingShader_NormalSource.cpp |
| +++ b/src/core/SkLightingShader_NormalSource.cpp |
| @@ -6,6 +6,7 @@ |
| */ |
| #include "SkBitmapProcShader.h" |
| +#include "SkBitmapProcState.h" |
| #include "SkError.h" |
| #include "SkErrorInternals.h" |
| #include "SkLightingShader.h" |
| @@ -41,12 +42,36 @@ public: |
| SkSourceGammaTreatment) const override; |
| #endif |
| + SkLightingShader::NormalSource::Provider* asProvider(const SkShader::ContextRec& rec, |
| + void* storage) const override; |
| + |
| + size_t providerSize() const override; |
| + |
| SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(NormalMapSourceImpl) |
| protected: |
| void flatten(SkWriteBuffer& buf) const override; |
| private: |
| + |
| + class Provider : public SkLightingShader::NormalSource::Provider { |
| + public: |
| + Provider(const NormalMapSourceImpl& source, SkBitmapProcState* state); |
| + |
| + virtual ~Provider(); |
| + |
| + void fillScanLine(int x, int y, SkPoint3 output[], int count) const override; |
| + |
| + int maxCountForFillScanLine(int count) const override; |
| + private: |
| + const NormalMapSourceImpl& fSource; |
|
egdaniel
2016/06/16 13:48:10
Generally we store pointers here if you just need
dvonbeck
2016/06/16 22:05:40
I did this because it's what LightingShader contex
|
| + SkBitmapProcState* fState; |
| + |
| + typedef SkLightingShader::NormalSource::Provider INHERITED; |
| + }; |
| + |
| + bool computeNormTotalInverse(const SkShader::ContextRec& rec, SkMatrix* normTotalInverse) const; |
| + |
| SkBitmap fNormalMap; |
| SkMatrix fNormLocalMatrix; |
| SkVector fInvNormRotation; |
| @@ -228,6 +253,91 @@ sk_sp<GrFragmentProcessor> NormalMapSourceImpl::asFragmentProcessor( |
| //////////////////////////////////////////////////////////////////////////// |
| +NormalMapSourceImpl::Provider::Provider(const NormalMapSourceImpl& source, SkBitmapProcState* state) |
| + : fSource(source) |
| + , fState(state) { |
| + SkASSERT(fState->fPixmap.addr()); |
| +} |
| + |
| +NormalMapSourceImpl::Provider::~Provider() { |
| + fState->~SkBitmapProcState(); |
| +} |
| + |
| +SkLightingShader::NormalSource::Provider* NormalMapSourceImpl::asProvider( |
| + const SkShader::ContextRec &rec, void *storage) const { |
| + SkMatrix normTotalInv; |
| + if (!this->computeNormTotalInverse(rec, &normTotalInv)) { |
| + return nullptr; |
| + } |
| + |
| + void* stateStorage = (char*)storage + sizeof(Provider); |
| + SkBitmapProcState* state = new (stateStorage) SkBitmapProcState(fNormalMap, |
| + SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, SkMipMap::DeduceTreatment(rec)); |
| + SkASSERT(state); |
| + if (!state->setup(normTotalInv, *rec.fPaint)) { |
| + state->~SkBitmapProcState(); |
| + return nullptr; |
| + } |
| + |
| + return new (storage) Provider(*this, state); |
| +} |
| + |
| +size_t NormalMapSourceImpl::providerSize() const { |
| + return sizeof(Provider) + sizeof(SkBitmapProcState); |
| +} |
| + |
| +// TODO: these defines are redundant with the ones in SkLightingShader.cpp, will consolidate in a |
| +// future CL when the source of diffuse colores is factored out |
| +#define TMP_COUNT 16 |
| +#define BUFFER_MAX (TMP_COUNT * sizeof(uint32_t)) |
| +void NormalMapSourceImpl::Provider::fillScanLine(int x, int y, SkPoint3 output[], |
| + int count) const { |
| + SkBitmapProcState::MatrixProc normalMProc = fState->getMatrixProc(); |
| + SkBitmapProcState::SampleProc32 normalSProc = fState->getSampleProc32(); |
| + |
| + uint32_t tmpNormal[BUFFER_MAX]; |
| + SkPMColor tmpNormal2[2*BUFFER_MAX]; |
| + normalMProc(*fState, tmpNormal, count, x, y); |
| + normalSProc(*fState, tmpNormal, count, tmpNormal2); |
| + |
| + for (int i = 0; i < count; i++) { |
| + SkASSERT(0xFF == SkColorGetA(tmpNormal2[i])); // opaque -> unpremul |
| + |
| + SkPoint3 tempNorm; |
| + |
| + tempNorm.set(SkIntToScalar(SkGetPackedR32(tmpNormal2[i])) - 127.0f, |
| + SkIntToScalar(SkGetPackedG32(tmpNormal2[i])) - 127.0f, |
| + SkIntToScalar(SkGetPackedB32(tmpNormal2[i])) - 127.0f); |
| + tempNorm.normalize(); |
| + |
| + |
| + output[i].fX = fSource.fInvNormRotation.fX * tempNorm.fX + |
| + fSource.fInvNormRotation.fY * tempNorm.fY; |
| + output[i].fY = -fSource.fInvNormRotation.fY * tempNorm.fX + |
| + fSource.fInvNormRotation.fX * tempNorm.fY; |
| + output[i].fZ = tempNorm.fZ; |
| + } |
| +} |
| + |
| +int NormalMapSourceImpl::Provider::maxCountForFillScanLine(int count) const { |
| + return fState->maxCountForBufferSize(sizeof(uint32_t /*tmpNormal[0]*/) * count); |
| +} |
| + |
| +bool NormalMapSourceImpl::computeNormTotalInverse(const SkShader::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); |
| +} |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| + |
| sk_sp<SkFlattenable> NormalMapSourceImpl::CreateProc(SkReadBuffer& buf) { |
| SkMatrix normLocalM; |