Index: src/core/SkLightingShader.cpp |
diff --git a/src/core/SkLightingShader.cpp b/src/core/SkLightingShader.cpp |
index 02f14b34ddc9215c72070aeedc769a8f36418cd2..52d9e987fa8ded6f5ded09e8de97fdb25ffaaf17 100644 |
--- a/src/core/SkLightingShader.cpp |
+++ b/src/core/SkLightingShader.cpp |
@@ -21,15 +21,11 @@ |
/* |
SkLightingShader TODOs: |
- support other than clamp mode |
- allow 'diffuse' & 'normal' to be of different dimensions? |
support different light types |
support multiple lights |
- enforce normal map is 4 channel |
- use SkImages instead if SkBitmaps |
+ fix non-opaque diffuse textures |
To Test: |
- non-opaque diffuse textures |
A8 diffuse textures |
down & upsampled draws |
*/ |
@@ -81,6 +77,7 @@ public: |
private: |
SkShader::Context* fDiffuseContext; |
SkNormalSource::Provider* fNormalProvider; |
+ SkColor fPaintColor; |
uint32_t fFlags; |
void* fHeapAllocated; |
@@ -270,18 +267,21 @@ sk_sp<GrFragmentProcessor> SkLightingShaderImpl::asFragmentProcessor( |
return nullptr; |
} |
- sk_sp<GrFragmentProcessor> fpPipeline[] = { |
- fDiffuseShader->asFragmentProcessor(context, viewM, localMatrix, filterQuality, |
- gammaTreatment), |
- sk_make_sp<LightingFP>(std::move(normalFP), fLights) |
- }; |
- if(!fpPipeline[0]) { |
- return nullptr; |
- } |
- |
- sk_sp<GrFragmentProcessor> inner(GrFragmentProcessor::RunInSeries(fpPipeline, 2)); |
+ if (fDiffuseShader) { |
+ sk_sp<GrFragmentProcessor> fpPipeline[] = { |
robertphillips
2016/07/11 14:02:04
this seems over tabbed
dvonbeck
2016/07/11 19:37:29
Done.
|
+ fDiffuseShader->asFragmentProcessor(context, viewM, localMatrix, filterQuality, |
+ gammaTreatment), |
+ sk_make_sp<LightingFP>(std::move(normalFP), fLights) |
+ }; |
+ if(!fpPipeline[0]) { |
+ return nullptr; |
+ } |
- return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner)); |
+ sk_sp<GrFragmentProcessor> innerLightFP = GrFragmentProcessor::RunInSeries(fpPipeline, 2); |
+ return GrFragmentProcessor::MulOutputByInputAlpha(std::move(innerLightFP)); |
+ } else { |
+ return sk_make_sp<LightingFP>(std::move(normalFP), fLights); |
egdaniel
2016/07/11 18:00:59
I think we still need to do the premul of alpha af
dvonbeck
2016/07/11 19:37:29
The alpha of the input color gets passed down to t
|
+ } |
} |
#endif |
@@ -289,7 +289,7 @@ sk_sp<GrFragmentProcessor> SkLightingShaderImpl::asFragmentProcessor( |
//////////////////////////////////////////////////////////////////////////// |
bool SkLightingShaderImpl::isOpaque() const { |
robertphillips
2016/07/11 14:02:04
Hmmm, what happens if the paint's color is transpa
dvonbeck
2016/07/11 19:37:29
I don't know :S, we don't know the paint at shader
robertphillips
2016/07/11 20:51:42
We can't pull the alpha out of 'fPaintColor' ?
dvonbeck
2016/07/12 21:01:44
No, fPaintColor is a field of LightingShaderContex
|
- return fDiffuseShader->isOpaque(); |
+ return (fDiffuseShader ? fDiffuseShader->isOpaque() : true); |
} |
SkLightingShaderImpl::LightingShaderContext::LightingShaderContext( |
@@ -308,13 +308,16 @@ SkLightingShaderImpl::LightingShaderContext::LightingShaderContext( |
flags |= kOpaqueAlpha_Flag; |
} |
+ fPaintColor = rec.fPaint->getColor(); |
fFlags = flags; |
} |
SkLightingShaderImpl::LightingShaderContext::~LightingShaderContext() { |
// The dependencies have been created outside of the context on memory that was allocated by |
// the onCreateContext() method. Call the destructors and free the memory. |
- fDiffuseContext->~Context(); |
+ if (fDiffuseContext) { |
+ fDiffuseContext->~Context(); |
+ } |
fNormalProvider->~Provider(); |
sk_free(fHeapAllocated); |
@@ -352,15 +355,21 @@ void SkLightingShaderImpl::LightingShaderContext::shadeSpan(int x, int y, |
SkPMColor diffuse[BUFFER_MAX]; |
SkPoint3 normals[BUFFER_MAX]; |
+ SkColor diffColor = fPaintColor; |
+ |
do { |
int n = SkTMin(count, BUFFER_MAX); |
- fDiffuseContext->shadeSpan(x, y, diffuse, n); |
fNormalProvider->fillScanLine(x, y, normals, n); |
- for (int i = 0; i < n; ++i) { |
+ if (fDiffuseContext) { |
+ fDiffuseContext->shadeSpan(x, y, diffuse, n); |
+ } |
- SkColor diffColor = SkUnPreMultiply::PMColorToColor(diffuse[i]); |
+ for (int i = 0; i < n; ++i) { |
+ if (fDiffuseContext) { |
+ diffColor = SkUnPreMultiply::PMColorToColor(diffuse[i]); |
+ } |
SkColor3f accum = SkColor3f::Make(0.0f, 0.0f, 0.0f); |
// This is all done in linear unpremul color space (each component 0..255.0f though) |
@@ -430,7 +439,12 @@ sk_sp<SkFlattenable> SkLightingShaderImpl::CreateProc(SkReadBuffer& buf) { |
sk_sp<SkLights> lights(builder.finish()); |
sk_sp<SkNormalSource> normalSource(buf.readFlattenable<SkNormalSource>()); |
- sk_sp<SkShader> diffuseShader(buf.readFlattenable<SkShader>()); |
+ |
+ bool hasDiffuse = buf.readBool(); |
+ sk_sp<SkShader> diffuseShader = nullptr; |
+ if (hasDiffuse) { |
+ diffuseShader = buf.readFlattenable<SkShader>(); |
+ } |
return sk_make_sp<SkLightingShaderImpl>(std::move(diffuseShader), std::move(normalSource), |
std::move(lights)); |
@@ -453,7 +467,10 @@ void SkLightingShaderImpl::flatten(SkWriteBuffer& buf) const { |
} |
buf.writeFlattenable(fNormalSource.get()); |
robertphillips
2016/07/11 14:02:04
Normally this would require a bump in the .skp ver
dvonbeck
2016/07/11 19:37:29
Acknowledged. It's changed quite a few times by no
|
- buf.writeFlattenable(fDiffuseShader.get()); |
+ buf.writeBool(fDiffuseShader); |
+ if (fDiffuseShader) { |
+ buf.writeFlattenable(fDiffuseShader.get()); |
+ } |
} |
size_t SkLightingShaderImpl::onContextSize(const ContextRec& rec) const { |
@@ -462,18 +479,23 @@ size_t SkLightingShaderImpl::onContextSize(const ContextRec& rec) const { |
SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec, |
void* storage) const { |
- size_t heapRequired = fDiffuseShader->contextSize(rec) + |
+ size_t heapRequired = (fDiffuseShader ? fDiffuseShader->contextSize(rec) : 0) + |
fNormalSource->providerSize(rec); |
void* heapAllocated = sk_malloc_throw(heapRequired); |
void* diffuseContextStorage = heapAllocated; |
- SkShader::Context* diffuseContext = fDiffuseShader->createContext(rec, diffuseContextStorage); |
- if (!diffuseContext) { |
- sk_free(heapAllocated); |
- return nullptr; |
+ void* normalProviderStorage = (char*) diffuseContextStorage + |
+ (fDiffuseShader ? fDiffuseShader->contextSize(rec) : 0); |
+ |
+ SkShader::Context *diffuseContext = nullptr; |
+ if (fDiffuseShader) { |
+ diffuseContext = fDiffuseShader->createContext(rec, diffuseContextStorage); |
+ if (!diffuseContext) { |
+ sk_free(heapAllocated); |
+ return nullptr; |
+ } |
} |
- void* normalProviderStorage = (char*)heapAllocated + fDiffuseShader->contextSize(rec); |
SkNormalSource::Provider* normalProvider = fNormalSource->asProvider(rec, |
normalProviderStorage); |
if (!normalProvider) { |
@@ -491,10 +513,8 @@ SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec, |
sk_sp<SkShader> SkLightingShader::Make(sk_sp<SkShader> diffuseShader, |
sk_sp<SkNormalSource> normalSource, |
sk_sp<SkLights> lights) { |
- if (!diffuseShader || !normalSource) { |
- // TODO: Use paint's color in absence of a diffuseShader |
- // TODO: Use a default implementation of normalSource instead |
- return nullptr; |
+ if (!normalSource) { |
+ normalSource = SkNormalSource::MakeFlat(); |
} |
return sk_make_sp<SkLightingShaderImpl>(std::move(diffuseShader), std::move(normalSource), |