Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1952)

Unified Diff: src/effects/SkLightingImageFilter.cpp

Issue 23295017: In image filters, apply the CTM and offset to the crop rect. This is necessary to compensate for bo… (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Fix documentation comment. Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/effects/SkColorFilterImageFilter.cpp ('k') | src/effects/SkMagnifierImageFilter.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/effects/SkLightingImageFilter.cpp
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
index ccb1dc5127357da4df535069bd3af6d8a1b2c247..e71df66e6c6888432d1a1094b20f140a2c058112 100644
--- a/src/effects/SkLightingImageFilter.cpp
+++ b/src/effects/SkLightingImageFilter.cpp
@@ -265,7 +265,7 @@ public:
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiffuseLightingImageFilter)
#if SK_SUPPORT_GPU
- virtual bool asNewEffect(GrEffectRef** effect, GrTexture*, const SkIPoint& offset) const SK_OVERRIDE;
+ virtual bool asNewEffect(GrEffectRef** effect, GrTexture*, const SkMatrix& matrix) const SK_OVERRIDE;
#endif
SkScalar kd() const { return fKD; }
@@ -287,7 +287,7 @@ public:
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpecularLightingImageFilter)
#if SK_SUPPORT_GPU
- virtual bool asNewEffect(GrEffectRef** effect, GrTexture*, const SkIPoint& offset) const SK_OVERRIDE;
+ virtual bool asNewEffect(GrEffectRef** effect, GrTexture*, const SkMatrix& matrix) const SK_OVERRIDE;
#endif
SkScalar ks() const { return fKS; }
@@ -309,12 +309,12 @@ private:
class GrLightingEffect : public GrSingleTextureEffect {
public:
- GrLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale, const SkIPoint& offset);
+ GrLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale, const SkMatrix& matrix);
virtual ~GrLightingEffect();
const SkLight* light() const { return fLight; }
SkScalar surfaceScale() const { return fSurfaceScale; }
- const SkIPoint& offset() const { return fOffset; }
+ const SkMatrix& filterMatrix() const { return fFilterMatrix; }
virtual void getConstantColorComponents(GrColor* color,
uint32_t* validFlags) const SK_OVERRIDE {
@@ -329,7 +329,7 @@ private:
typedef GrSingleTextureEffect INHERITED;
const SkLight* fLight;
SkScalar fSurfaceScale;
- SkIPoint fOffset;
+ SkMatrix fFilterMatrix;
};
class GrDiffuseLightingEffect : public GrLightingEffect {
@@ -337,12 +337,12 @@ public:
static GrEffectRef* Create(GrTexture* texture,
const SkLight* light,
SkScalar surfaceScale,
- const SkIPoint& offset,
+ const SkMatrix& matrix,
SkScalar kd) {
AutoEffectUnref effect(SkNEW_ARGS(GrDiffuseLightingEffect, (texture,
light,
surfaceScale,
- offset,
+ matrix,
kd)));
return CreateEffectRef(effect);
}
@@ -360,7 +360,7 @@ private:
GrDiffuseLightingEffect(GrTexture* texture,
const SkLight* light,
SkScalar surfaceScale,
- const SkIPoint& offset,
+ const SkMatrix& matrix,
SkScalar kd);
GR_DECLARE_EFFECT_TEST;
@@ -373,13 +373,13 @@ public:
static GrEffectRef* Create(GrTexture* texture,
const SkLight* light,
SkScalar surfaceScale,
- const SkIPoint& offset,
+ const SkMatrix& matrix,
SkScalar ks,
SkScalar shininess) {
AutoEffectUnref effect(SkNEW_ARGS(GrSpecularLightingEffect, (texture,
light,
surfaceScale,
- offset,
+ matrix,
ks,
shininess)));
return CreateEffectRef(effect);
@@ -398,7 +398,7 @@ private:
GrSpecularLightingEffect(GrTexture* texture,
const SkLight* light,
SkScalar surfaceScale,
- const SkIPoint& offset,
+ const SkMatrix& matrix,
SkScalar ks,
SkScalar shininess);
@@ -434,8 +434,7 @@ public:
// This is called from GrGLLightingEffect's setData(). Subclasses of GrGLLight must call
// INHERITED::setData().
virtual void setData(const GrGLUniformManager&,
- const SkLight* light,
- const SkIPoint& offset) const;
+ const SkLight* light) const;
protected:
/**
@@ -456,8 +455,7 @@ class GrGLDistantLight : public GrGLLight {
public:
virtual ~GrGLDistantLight() {}
virtual void setData(const GrGLUniformManager&,
- const SkLight* light,
- const SkIPoint& offset) const SK_OVERRIDE;
+ const SkLight* light) const SK_OVERRIDE;
virtual void emitSurfaceToLight(GrGLShaderBuilder*, const char* z) SK_OVERRIDE;
private:
@@ -471,8 +469,7 @@ class GrGLPointLight : public GrGLLight {
public:
virtual ~GrGLPointLight() {}
virtual void setData(const GrGLUniformManager&,
- const SkLight* light,
- const SkIPoint& offset) const SK_OVERRIDE;
+ const SkLight* light) const SK_OVERRIDE;
virtual void emitSurfaceToLight(GrGLShaderBuilder*, const char* z) SK_OVERRIDE;
private:
@@ -486,8 +483,7 @@ class GrGLSpotLight : public GrGLLight {
public:
virtual ~GrGLSpotLight() {}
virtual void setData(const GrGLUniformManager&,
- const SkLight* light,
- const SkIPoint& offset) const SK_OVERRIDE;
+ const SkLight* light) const SK_OVERRIDE;
virtual void emitSurfaceToLight(GrGLShaderBuilder*, const char* z) SK_OVERRIDE;
virtual void emitLightColor(GrGLShaderBuilder*, const char *surfaceToLight) SK_OVERRIDE;
@@ -529,12 +525,15 @@ public:
}
// Called to know whether the generated GrGLLight will require access to the fragment position.
virtual bool requiresFragmentPosition() const = 0;
+ virtual SkLight* transform(const SkMatrix& matrix) const = 0;
protected:
SkLight(SkColor color)
: fColor(SkIntToScalar(SkColorGetR(color)),
SkIntToScalar(SkColorGetG(color)),
SkIntToScalar(SkColorGetB(color))) {}
+ SkLight(const SkPoint3& color)
+ : fColor(color) {}
SkLight(SkFlattenableReadBuffer& buffer)
: INHERITED(buffer) {
fColor = readPoint3(buffer);
@@ -588,9 +587,15 @@ public:
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDistantLight)
protected:
+ SkDistantLight(const SkPoint3& direction, const SkPoint3& color)
+ : INHERITED(color), fDirection(direction) {
+ }
SkDistantLight(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
fDirection = readPoint3(buffer);
}
+ virtual SkLight* transform(const SkMatrix& matrix) const {
+ return new SkDistantLight(direction(), color());
+ }
virtual void flatten(SkFlattenableWriteBuffer& buffer) const {
INHERITED::flatten(buffer);
writePoint3(fDirection, buffer);
@@ -635,6 +640,12 @@ public:
return INHERITED::isEqual(other) &&
fLocation == o.fLocation;
}
+ virtual SkLight* transform(const SkMatrix& matrix) const {
+ SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
+ matrix.mapPoints(&location2, 1);
+ SkPoint3 location(location2.fX, location2.fY, fLocation.fZ);
+ return new SkPointLight(location, color());
+ }
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPointLight)
@@ -642,6 +653,8 @@ protected:
SkPointLight(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
fLocation = readPoint3(buffer);
}
+ SkPointLight(const SkPoint3& location, const SkPoint3& color)
+ : INHERITED(color), fLocation(location) {}
virtual void flatten(SkFlattenableWriteBuffer& buffer) const {
INHERITED::flatten(buffer);
writePoint3(fLocation, buffer);
@@ -670,6 +683,16 @@ public:
fConeScale = SkScalarInvert(antiAliasThreshold);
}
+ virtual SkLight* transform(const SkMatrix& matrix) const {
+ SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
+ matrix.mapPoints(&location2, 1);
+ SkPoint3 location(location2.fX, location2.fY, fLocation.fZ);
+ SkPoint target2 = SkPoint::Make(fTarget.fX, fTarget.fY);
+ matrix.mapPoints(&target2, 1);
+ SkPoint3 target(target2.fX, target2.fY, fTarget.fZ);
+ return new SkSpotLight(location, target, fSpecularExponent, fCosOuterConeAngle, fCosInnerConeAngle, fConeScale, fS, color());
+ }
+
SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
SkPoint3 direction(fLocation.fX - SkIntToScalar(x),
fLocation.fY - SkIntToScalar(y),
@@ -719,6 +742,17 @@ protected:
fConeScale = buffer.readScalar();
fS = readPoint3(buffer);
}
+ SkSpotLight(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cosOuterConeAngle, SkScalar cosInnerConeAngle, SkScalar coneScale, const SkPoint3& s, const SkPoint3& color)
+ : INHERITED(color),
+ fLocation(location),
+ fTarget(target),
+ fSpecularExponent(specularExponent),
+ fCosOuterConeAngle(cosOuterConeAngle),
+ fCosInnerConeAngle(cosInnerConeAngle),
+ fConeScale(coneScale),
+ fS(s)
+ {
+ }
virtual void flatten(SkFlattenableWriteBuffer& buffer) const {
INHERITED::flatten(buffer);
writePoint3(fLocation, buffer);
@@ -857,7 +891,7 @@ void SkDiffuseLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) con
bool SkDiffuseLightingImageFilter::onFilterImage(Proxy*,
const SkBitmap& src,
- const SkMatrix&,
+ const SkMatrix& ctm,
SkBitmap* dst,
SkIPoint* offset) {
if (src.config() != SkBitmap::kARGB_8888_Config) {
@@ -870,7 +904,7 @@ bool SkDiffuseLightingImageFilter::onFilterImage(Proxy*,
SkIRect bounds;
src.getBounds(&bounds);
- if (!this->applyCropRect(&bounds)) {
+ if (!this->applyCropRect(&bounds, ctm)) {
return false;
}
@@ -881,16 +915,18 @@ bool SkDiffuseLightingImageFilter::onFilterImage(Proxy*,
dst->setConfig(src.config(), bounds.width(), bounds.height());
dst->allocPixels();
+ SkAutoTUnref<SkLight> transformedLight(light()->transform(ctm));
+
DiffuseLightingType lightingType(fKD);
- switch (light()->type()) {
+ switch (transformedLight->type()) {
case SkLight::kDistant_LightType:
- lightBitmap<DiffuseLightingType, SkDistantLight>(lightingType, light(), src, dst, surfaceScale(), bounds);
+ lightBitmap<DiffuseLightingType, SkDistantLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
break;
case SkLight::kPoint_LightType:
- lightBitmap<DiffuseLightingType, SkPointLight>(lightingType, light(), src, dst, surfaceScale(), bounds);
+ lightBitmap<DiffuseLightingType, SkPointLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
break;
case SkLight::kSpot_LightType:
- lightBitmap<DiffuseLightingType, SkSpotLight>(lightingType, light(), src, dst, surfaceScale(), bounds);
+ lightBitmap<DiffuseLightingType, SkSpotLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
break;
}
@@ -900,10 +936,10 @@ bool SkDiffuseLightingImageFilter::onFilterImage(Proxy*,
}
#if SK_SUPPORT_GPU
-bool SkDiffuseLightingImageFilter::asNewEffect(GrEffectRef** effect, GrTexture* texture, const SkIPoint& offset) const {
+bool SkDiffuseLightingImageFilter::asNewEffect(GrEffectRef** effect, GrTexture* texture, const SkMatrix& matrix) const {
if (effect) {
SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
- *effect = GrDiffuseLightingEffect::Create(texture, light(), scale, offset, kd());
+ *effect = GrDiffuseLightingEffect::Create(texture, light(), scale, matrix, kd());
}
return true;
}
@@ -933,7 +969,7 @@ void SkSpecularLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) co
bool SkSpecularLightingImageFilter::onFilterImage(Proxy*,
const SkBitmap& src,
- const SkMatrix&,
+ const SkMatrix& ctm,
SkBitmap* dst,
SkIPoint* offset) {
if (src.config() != SkBitmap::kARGB_8888_Config) {
@@ -946,7 +982,7 @@ bool SkSpecularLightingImageFilter::onFilterImage(Proxy*,
SkIRect bounds;
src.getBounds(&bounds);
- if (!this->applyCropRect(&bounds)) {
+ if (!this->applyCropRect(&bounds, ctm)) {
return false;
}
@@ -958,15 +994,16 @@ bool SkSpecularLightingImageFilter::onFilterImage(Proxy*,
dst->allocPixels();
SpecularLightingType lightingType(fKS, fShininess);
- switch (light()->type()) {
+ SkAutoTUnref<SkLight> transformedLight(light()->transform(ctm));
+ switch (transformedLight->type()) {
case SkLight::kDistant_LightType:
- lightBitmap<SpecularLightingType, SkDistantLight>(lightingType, light(), src, dst, surfaceScale(), bounds);
+ lightBitmap<SpecularLightingType, SkDistantLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
break;
case SkLight::kPoint_LightType:
- lightBitmap<SpecularLightingType, SkPointLight>(lightingType, light(), src, dst, surfaceScale(), bounds);
+ lightBitmap<SpecularLightingType, SkPointLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
break;
case SkLight::kSpot_LightType:
- lightBitmap<SpecularLightingType, SkSpotLight>(lightingType, light(), src, dst, surfaceScale(), bounds);
+ lightBitmap<SpecularLightingType, SkSpotLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
break;
}
offset->fX += bounds.left();
@@ -975,10 +1012,10 @@ bool SkSpecularLightingImageFilter::onFilterImage(Proxy*,
}
#if SK_SUPPORT_GPU
-bool SkSpecularLightingImageFilter::asNewEffect(GrEffectRef** effect, GrTexture* texture, const SkIPoint& offset) const {
+bool SkSpecularLightingImageFilter::asNewEffect(GrEffectRef** effect, GrTexture* texture, const SkMatrix& matrix) const {
if (effect) {
SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
- *effect = GrSpecularLightingEffect::Create(texture, light(), scale, offset, ks(), shininess());
+ *effect = GrSpecularLightingEffect::Create(texture, light(), scale, matrix, ks(), shininess());
}
return true;
}
@@ -1087,11 +1124,11 @@ private:
GrLightingEffect::GrLightingEffect(GrTexture* texture,
const SkLight* light,
SkScalar surfaceScale,
- const SkIPoint& offset)
+ const SkMatrix& matrix)
: INHERITED(texture, MakeDivByTextureWHMatrix(texture))
, fLight(light)
, fSurfaceScale(surfaceScale)
- , fOffset(offset) {
+ , fFilterMatrix(matrix) {
fLight->ref();
if (light->requiresFragmentPosition()) {
this->setWillReadFragmentPosition();
@@ -1114,9 +1151,9 @@ bool GrLightingEffect::onIsEqual(const GrEffect& sBase) const {
GrDiffuseLightingEffect::GrDiffuseLightingEffect(GrTexture* texture,
const SkLight* light,
SkScalar surfaceScale,
- const SkIPoint& offset,
+ const SkMatrix& matrix,
SkScalar kd)
- : INHERITED(texture, light, surfaceScale, offset), fKD(kd) {
+ : INHERITED(texture, light, surfaceScale, matrix), fKD(kd) {
}
const GrBackendEffectFactory& GrDiffuseLightingEffect::getFactory() const {
@@ -1138,9 +1175,12 @@ GrEffectRef* GrDiffuseLightingEffect::TestCreate(SkMWCRandom* random,
SkScalar surfaceScale = random->nextSScalar1();
SkScalar kd = random->nextUScalar1();
SkAutoTUnref<SkLight> light(create_random_light(random));
- SkIPoint offset = SkIPoint::Make(random->nextS(), random->nextS());
+ SkMatrix matrix;
+ for (int i = 0; i < 9; i++) {
+ matrix[i] = random->nextUScalar1();
+ }
return GrDiffuseLightingEffect::Create(textures[GrEffectUnitTest::kAlphaTextureIdx],
- light, surfaceScale, offset, kd);
+ light, surfaceScale, matrix, kd);
}
@@ -1278,7 +1318,8 @@ void GrGLLightingEffect::setData(const GrGLUniformManager& uman,
float ySign = texture->origin() == kTopLeft_GrSurfaceOrigin ? -1.0f : 1.0f;
uman.set2f(fImageIncrementUni, 1.0f / texture->width(), ySign / texture->height());
uman.set1f(fSurfaceScaleUni, lighting.surfaceScale());
- fLight->setData(uman, lighting.light(), lighting.offset());
+ SkAutoTUnref<SkLight> transformedLight(lighting.light()->transform(lighting.filterMatrix()));
+ fLight->setData(uman, transformedLight);
fEffectMatrix.setData(uman,
lighting.getMatrix(),
drawEffect,
@@ -1330,10 +1371,10 @@ void GrGLDiffuseLightingEffect::setData(const GrGLUniformManager& uman,
GrSpecularLightingEffect::GrSpecularLightingEffect(GrTexture* texture,
const SkLight* light,
SkScalar surfaceScale,
- const SkIPoint& offset,
+ const SkMatrix& matrix,
SkScalar ks,
SkScalar shininess)
- : INHERITED(texture, light, surfaceScale, offset),
+ : INHERITED(texture, light, surfaceScale, matrix),
fKS(ks),
fShininess(shininess) {
}
@@ -1359,9 +1400,12 @@ GrEffectRef* GrSpecularLightingEffect::TestCreate(SkMWCRandom* random,
SkScalar ks = random->nextUScalar1();
SkScalar shininess = random->nextUScalar1();
SkAutoTUnref<SkLight> light(create_random_light(random));
- SkIPoint offset = SkIPoint::Make(random->nextS(), random->nextS());
+ SkMatrix matrix;
+ for (int i = 0; i < 9; i++) {
+ matrix[i] = random->nextUScalar1();
+ }
return GrSpecularLightingEffect::Create(textures[GrEffectUnitTest::kAlphaTextureIdx],
- light, surfaceScale, offset, ks, shininess);
+ light, surfaceScale, matrix, ks, shininess);
}
///////////////////////////////////////////////////////////////////////////////
@@ -1419,17 +1463,15 @@ void GrGLLight::emitLightColor(GrGLShaderBuilder* builder,
}
void GrGLLight::setData(const GrGLUniformManager& uman,
- const SkLight* light,
- const SkIPoint&) const {
+ const SkLight* light) const {
setUniformPoint3(uman, fColorUni, light->color() * SkScalarInvert(SkIntToScalar(255)));
}
///////////////////////////////////////////////////////////////////////////////
void GrGLDistantLight::setData(const GrGLUniformManager& uman,
- const SkLight* light,
- const SkIPoint& offset) const {
- INHERITED::setData(uman, light, offset);
+ const SkLight* light) const {
+ INHERITED::setData(uman, light);
SkASSERT(light->type() == SkLight::kDistant_LightType);
const SkDistantLight* distantLight = static_cast<const SkDistantLight*>(light);
setUniformNormal3(uman, fDirectionUni, distantLight->direction());
@@ -1445,15 +1487,11 @@ void GrGLDistantLight::emitSurfaceToLight(GrGLShaderBuilder* builder, const char
///////////////////////////////////////////////////////////////////////////////
void GrGLPointLight::setData(const GrGLUniformManager& uman,
- const SkLight* light,
- const SkIPoint& offset) const {
- INHERITED::setData(uman, light, offset);
+ const SkLight* light) const {
+ INHERITED::setData(uman, light);
SkASSERT(light->type() == SkLight::kPoint_LightType);
const SkPointLight* pointLight = static_cast<const SkPointLight*>(light);
- SkPoint3 location = pointLight->location();
- location.fX -= offset.fX;
- location.fY -= offset.fY;
- setUniformPoint3(uman, fLocationUni, location);
+ setUniformPoint3(uman, fLocationUni, pointLight->location());
}
void GrGLPointLight::emitSurfaceToLight(GrGLShaderBuilder* builder, const char* z) {
@@ -1466,15 +1504,11 @@ void GrGLPointLight::emitSurfaceToLight(GrGLShaderBuilder* builder, const char*
///////////////////////////////////////////////////////////////////////////////
void GrGLSpotLight::setData(const GrGLUniformManager& uman,
- const SkLight* light,
- const SkIPoint& offset) const {
- INHERITED::setData(uman, light, offset);
+ const SkLight* light) const {
+ INHERITED::setData(uman, light);
SkASSERT(light->type() == SkLight::kSpot_LightType);
const SkSpotLight* spotLight = static_cast<const SkSpotLight *>(light);
- SkPoint3 location = spotLight->location();
- location.fX -= offset.fX;
- location.fY -= offset.fY;
- setUniformPoint3(uman, fLocationUni, location);
+ setUniformPoint3(uman, fLocationUni, spotLight->location());
uman.set1f(fExponentUni, spotLight->specularExponent());
uman.set1f(fCosInnerConeAngleUni, spotLight->cosInnerConeAngle());
uman.set1f(fCosOuterConeAngleUni, spotLight->cosOuterConeAngle());
« no previous file with comments | « src/effects/SkColorFilterImageFilter.cpp ('k') | src/effects/SkMagnifierImageFilter.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698