aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkLightingShader.cpp
diff options
context:
space:
mode:
authorGravatar dvonbeck <dvonbeck@google.com>2016-06-27 11:40:45 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-06-27 11:40:45 -0700
commit12c4fc2579017a162668db077e8067512fd968ca (patch)
tree5337853b1101385452b5cd0c473c8fd9e2bb125e /src/core/SkLightingShader.cpp
parent8bad3acce52a24fb99d3201a0cefa54eacf9ee57 (diff)
SkLightingShader normal vector CPU computation refactor.
The purpose of this change is to refactor the handling of normal maps out of SkLightingShader, laying the groundwork to eventually allow for multiple normal sources. This CL's base was the CL for GPU handling: https://codereview.chromium.org/2043393002/ What this CL includes: - A refactor of the SkLightingShader context's code that deals with reading normals off of a normal map. This is now abstracted out into a NormalSource::Provider class that the context uses. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2050773002 Committed: https://skia.googlesource.com/skia/+/790a70118327a129cb6b48fabe80f4e184c1e67c Review-Url: https://codereview.chromium.org/2050773002
Diffstat (limited to 'src/core/SkLightingShader.cpp')
-rw-r--r--src/core/SkLightingShader.cpp119
1 files changed, 46 insertions, 73 deletions
diff --git a/src/core/SkLightingShader.cpp b/src/core/SkLightingShader.cpp
index ca1c3417b4..f32aa9f411 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,8 @@ 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*,
+ void* heapAllocated);
~LightingShaderContext() override;
void shadeSpan(int x, int y, SkPMColor[], int count) override;
@@ -96,9 +98,11 @@ public:
uint32_t getFlags() const override { return fFlags; }
private:
- SkBitmapProcState* fDiffuseState;
- SkBitmapProcState* fNormalState;
- uint32_t fFlags;
+ SkBitmapProcState* fDiffuseState;
+ SkNormalSource::Provider* fNormalProvider;
+ uint32_t fFlags;
+
+ void* fHeapAllocated;
typedef SkShader::Context INHERITED;
};
@@ -110,7 +114,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 +124,7 @@ private:
SkMatrix fNormLocalMatrix;
SkVector fInvNormRotation;
- sk_sp<SkLightingShader::NormalSource> fNormalSource;
+ sk_sp<SkNormalSource> fNormalSource;
friend class SkLightingShader;
@@ -367,13 +370,12 @@ 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, void* heapAllocated)
: INHERITED(shader, rec)
, fDiffuseState(diffuseState)
- , fNormalState(normalState) {
+ , fNormalProvider(normalProvider)
+ , fHeapAllocated(heapAllocated) {
const SkPixmap& pixmap = fDiffuseState->fPixmap;
bool isOpaque = pixmap.isOpaque();
@@ -390,7 +392,9 @@ 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();
+
+ sk_free(fHeapAllocated);
}
static inline SkPMColor convert(SkColor3f color, U8CPU a) {
@@ -417,29 +421,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 +449,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 +463,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 +550,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 +585,8 @@ 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);
}
SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec,
@@ -623,35 +596,31 @@ 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;
- }
+ size_t heapRequired = sizeof(SkBitmapProcState) + fNormalSource->providerSize(rec);
+ void* heapAllocated = sk_malloc_throw(heapRequired);
- void* diffuseStateStorage = (char*)storage + sizeof(LightingShaderContext);
+ void* diffuseStateStorage = heapAllocated;
SkBitmapProcState* diffuseState = new (diffuseStateStorage) SkBitmapProcState(fDiffuseMap,
SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
SkMipMap::DeduceTreatment(rec));
SkASSERT(diffuseState);
if (!diffuseState->setup(diffTotalInv, *rec.fPaint)) {
diffuseState->~SkBitmapProcState();
+ sk_free(heapAllocated);
return nullptr;
}
+ void* normalProviderStorage = (char*)heapAllocated + 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();
+ sk_free(heapAllocated);
return nullptr;
}
- return new (storage) LightingShaderContext(*this, rec, diffuseState, normalState);
+ return new (storage) LightingShaderContext(*this, rec, diffuseState, normalProvider,
+ heapAllocated);
}
///////////////////////////////////////////////////////////////////////////////
@@ -668,8 +637,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));