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; |