In image filters, apply the CTM and offset to the crop rect. This is necessary to compensate for both clipping applied by the compositor (communicated via the CTM) and for cropping applied in upstream image filters (communicated via the offset). This requires a few ugly conversions, since the crop rect is an SkIRect, and the ctm is an SkMatrix.
I also had to offset the matrix passed to filter evaluation by drawSprite() and internalDrawBitmap() by the primitive position. This is the same offset that is applied when drawing the primitive, to compensate for the internal saveLayer().
Also apply the total matrix to the filter params in asNewEffect(), so that (for example) lighting params are offset by both the compositor clipping and upstream crop rects.
R=reed@google.com
Review URL: https://codereview.chromium.org/23295017
git-svn-id: http://skia.googlecode.com/svn/trunk@10961 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gm/lighting.cpp b/gm/lighting.cpp
index f16e781..330e0ee 100644
--- a/gm/lighting.cpp
+++ b/gm/lighting.cpp
@@ -44,9 +44,10 @@
void drawClippedBitmap(SkCanvas* canvas, const SkPaint& paint, int x, int y) {
canvas->save();
- canvas->clipRect(SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y),
- SkIntToScalar(fBitmap.width()), SkIntToScalar(fBitmap.height())));
- canvas->drawBitmap(fBitmap, SkIntToScalar(x), SkIntToScalar(y), &paint);
+ canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
+ canvas->clipRect(SkRect::MakeWH(
+ SkIntToScalar(fBitmap.width()), SkIntToScalar(fBitmap.height())));
+ canvas->drawBitmap(fBitmap, 0, 0, &paint);
canvas->restore();
}
@@ -91,18 +92,24 @@
const SkIRect* cr = (i == 0) ? NULL : &cropRect;
paint.setImageFilter(SkLightingImageFilter::CreatePointLitDiffuse(pointLocation, white, surfaceScale, kd, NULL, cr))->unref();
drawClippedBitmap(canvas, paint, 0, y);
+
paint.setImageFilter(SkLightingImageFilter::CreateDistantLitDiffuse(distantDirection, white, surfaceScale, kd, NULL, cr))->unref();
drawClippedBitmap(canvas, paint, 110, y);
+
paint.setImageFilter(SkLightingImageFilter::CreateSpotLitDiffuse(spotLocation, spotTarget, spotExponent, cutoffAngle, white, surfaceScale, kd, NULL, cr))->unref();
drawClippedBitmap(canvas, paint, 220, y);
y += 110;
+
paint.setImageFilter(SkLightingImageFilter::CreatePointLitSpecular(pointLocation, white, surfaceScale, ks, shininess, NULL, cr))->unref();
drawClippedBitmap(canvas, paint, 0, y);
+
paint.setImageFilter(SkLightingImageFilter::CreateDistantLitSpecular(distantDirection, white, surfaceScale, ks, shininess, NULL, cr))->unref();
drawClippedBitmap(canvas, paint, 110, y);
+
paint.setImageFilter(SkLightingImageFilter::CreateSpotLitSpecular(spotLocation, spotTarget, spotExponent, cutoffAngle, white, surfaceScale, ks, shininess, NULL, cr))->unref();
drawClippedBitmap(canvas, paint, 220, y);
+
y += 110;
}
}
diff --git a/include/core/SkImageFilter.h b/include/core/SkImageFilter.h
index 01b3e0b..7b9dd32 100644
--- a/include/core/SkImageFilter.h
+++ b/include/core/SkImageFilter.h
@@ -77,16 +77,18 @@
* caller to unref it.
*
* The effect can assume its vertexCoords space maps 1-to-1 with texels
- * in the texture. "offset" is the delta between the source and
- * destination rect's origins, when cropped processing is being performed.
+ * in the texture. "matrix" is a transformation to apply to filter
+ * parameters before they are used in the effect. Note that this function
+ * will be called with (NULL, NULL, SkMatrix::I()) to query for support,
+ * so returning "true" indicates support for all possible matrices.
*/
- virtual bool asNewEffect(GrEffectRef** effect, GrTexture*, const SkIPoint& offset) const;
+ virtual bool asNewEffect(GrEffectRef** effect, GrTexture*, const SkMatrix& matrix) const;
/**
* Returns true if the filter can be processed on the GPU. This is most
* often used for multi-pass effects, where intermediate results must be
* rendered to textures. For single-pass effects, use asNewEffect().
- * The default implementation returns asNewEffect(NULL, NULL).
+ * The default implementation returns asNewEffect(NULL, NULL, SkMatrix::I()).
*/
virtual bool canFilterImageGPU() const;
@@ -159,9 +161,10 @@
// Default impl copies src into dst and returns true
virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*);
- // Sets rect to the intersection of rect and the crop rect. If there
- // is no overlap, returns false and leaves rect unchanged.
- bool applyCropRect(SkIRect* rect) const;
+ // Applies "matrix" to the crop rect, and sets "rect" to the intersection of
+ // "rect" and the transformed crop rect. If there is no overlap, returns
+ // false and leaves "rect" unchanged.
+ bool applyCropRect(SkIRect* rect, const SkMatrix& matrix) const;
private:
typedef SkFlattenable INHERITED;
diff --git a/include/effects/SkMagnifierImageFilter.h b/include/effects/SkMagnifierImageFilter.h
index b5cbd74..31b446f 100644
--- a/include/effects/SkMagnifierImageFilter.h
+++ b/include/effects/SkMagnifierImageFilter.h
@@ -17,7 +17,7 @@
SkMagnifierImageFilter(SkRect srcRect, SkScalar inset);
#if SK_SUPPORT_GPU
- virtual bool asNewEffect(GrEffectRef** effect, GrTexture* texture, const SkIPoint& offset) const SK_OVERRIDE;
+ virtual bool asNewEffect(GrEffectRef** effect, GrTexture* texture, const SkMatrix& matrix) const SK_OVERRIDE;
#endif
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMagnifierImageFilter)
diff --git a/include/effects/SkMatrixConvolutionImageFilter.h b/include/effects/SkMatrixConvolutionImageFilter.h
index 71c8938..b2602fe 100644
--- a/include/effects/SkMatrixConvolutionImageFilter.h
+++ b/include/effects/SkMatrixConvolutionImageFilter.h
@@ -62,7 +62,7 @@
SkBitmap* result, SkIPoint* loc) SK_OVERRIDE;
#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
private:
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index c59cd04..ff688f5 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -999,7 +999,9 @@
SkDeviceImageFilterProxy proxy(dstDev);
SkBitmap dst;
const SkBitmap& src = srcDev->accessBitmap(false);
- if (filter->filterImage(&proxy, src, *iter.fMatrix, &dst, &pos)) {
+ SkMatrix matrix = *iter.fMatrix;
+ matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y));
+ if (filter->filterImage(&proxy, src, matrix, &dst, &pos)) {
SkPaint tmpUnfiltered(*paint);
tmpUnfiltered.setImageFilter(NULL);
dstDev->drawSprite(iter, dst, pos.x(), pos.y(), tmpUnfiltered);
@@ -1034,8 +1036,9 @@
if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
SkDeviceImageFilterProxy proxy(iter.fDevice);
SkBitmap dst;
- if (filter->filterImage(&proxy, bitmap, *iter.fMatrix,
- &dst, &pos)) {
+ SkMatrix matrix = *iter.fMatrix;
+ matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y));
+ if (filter->filterImage(&proxy, bitmap, matrix, &dst, &pos)) {
SkPaint tmpUnfiltered(*paint);
tmpUnfiltered.setImageFilter(NULL);
iter.fDevice->drawSprite(iter, dst, pos.x(), pos.y(),
diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp
index 222a029..502613b 100644
--- a/src/core/SkImageFilter.cpp
+++ b/src/core/SkImageFilter.cpp
@@ -102,7 +102,7 @@
}
bool SkImageFilter::canFilterImageGPU() const {
- return this->asNewEffect(NULL, NULL, SkIPoint::Make(0, 0));
+ return this->asNewEffect(NULL, NULL, SkMatrix::I());
}
bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
@@ -116,7 +116,7 @@
GrTexture* srcTexture = input.getTexture();
SkIRect bounds;
src.getBounds(&bounds);
- if (!this->applyCropRect(&bounds)) {
+ if (!this->applyCropRect(&bounds, ctm)) {
return false;
}
SkRect srcRect = SkRect::Make(bounds);
@@ -135,7 +135,9 @@
GrContext::AutoRenderTarget art(context, dst.texture()->asRenderTarget());
GrContext::AutoClip acs(context, dstRect);
GrEffectRef* effect;
- this->asNewEffect(&effect, srcTexture, SkIPoint::Make(bounds.left(), bounds.top()));
+ SkMatrix matrix(ctm);
+ matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
+ this->asNewEffect(&effect, srcTexture, matrix);
SkASSERT(effect);
SkAutoUnref effectRef(effect);
GrPaint paint;
@@ -152,8 +154,17 @@
#endif
}
-bool SkImageFilter::applyCropRect(SkIRect* rect) const {
- return rect->intersect(fCropRect);
+bool SkImageFilter::applyCropRect(SkIRect* rect, const SkMatrix& matrix) const {
+ SkRect cropRect;
+ matrix.mapRect(&cropRect, SkRect::Make(fCropRect));
+ SkIRect cropRectI;
+ cropRect.roundOut(&cropRectI);
+ // If the original crop rect edges were unset, max out the new crop edges
+ if (fCropRect.fLeft == SK_MinS32) cropRectI.fLeft = SK_MinS32;
+ if (fCropRect.fTop == SK_MinS32) cropRectI.fTop = SK_MinS32;
+ if (fCropRect.fRight == SK_MaxS32) cropRectI.fRight = SK_MaxS32;
+ if (fCropRect.fBottom == SK_MaxS32) cropRectI.fBottom = SK_MaxS32;
+ return rect->intersect(cropRectI);
}
bool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
@@ -162,7 +173,7 @@
return true;
}
-bool SkImageFilter::asNewEffect(GrEffectRef**, GrTexture*, const SkIPoint& offset) const {
+bool SkImageFilter::asNewEffect(GrEffectRef**, GrTexture*, const SkMatrix&) const {
return false;
}
diff --git a/src/effects/SkBlurImageFilter.cpp b/src/effects/SkBlurImageFilter.cpp
index 4b2d3b8..3f97ddd 100644
--- a/src/effects/SkBlurImageFilter.cpp
+++ b/src/effects/SkBlurImageFilter.cpp
@@ -158,7 +158,7 @@
SkIRect srcBounds, dstBounds;
src.getBounds(&srcBounds);
- if (!this->applyCropRect(&srcBounds)) {
+ if (!this->applyCropRect(&srcBounds, ctm)) {
return false;
}
@@ -216,7 +216,7 @@
GrTexture* source = input.getTexture();
SkIRect rect;
src.getBounds(&rect);
- if (!this->applyCropRect(&rect)) {
+ if (!this->applyCropRect(&rect, ctm)) {
return false;
}
SkAutoTUnref<GrTexture> tex(SkGpuBlurUtils::GaussianBlur(source->getContext(),
diff --git a/src/effects/SkColorFilterImageFilter.cpp b/src/effects/SkColorFilterImageFilter.cpp
index 9c2c54e..16a36bb 100755
--- a/src/effects/SkColorFilterImageFilter.cpp
+++ b/src/effects/SkColorFilterImageFilter.cpp
@@ -107,7 +107,7 @@
SkIRect bounds;
src.getBounds(&bounds);
- if (!this->applyCropRect(&bounds)) {
+ if (!this->applyCropRect(&bounds, matrix)) {
return false;
}
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
index ccb1dc5..e71df66 100644
--- a/src/effects/SkLightingImageFilter.cpp
+++ b/src/effects/SkLightingImageFilter.cpp
@@ -265,7 +265,7 @@
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 @@
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 @@
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 @@
typedef GrSingleTextureEffect INHERITED;
const SkLight* fLight;
SkScalar fSurfaceScale;
- SkIPoint fOffset;
+ SkMatrix fFilterMatrix;
};
class GrDiffuseLightingEffect : public GrLightingEffect {
@@ -337,12 +337,12 @@
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 @@
GrDiffuseLightingEffect(GrTexture* texture,
const SkLight* light,
SkScalar surfaceScale,
- const SkIPoint& offset,
+ const SkMatrix& matrix,
SkScalar kd);
GR_DECLARE_EFFECT_TEST;
@@ -373,13 +373,13 @@
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 @@
GrSpecularLightingEffect(GrTexture* texture,
const SkLight* light,
SkScalar surfaceScale,
- const SkIPoint& offset,
+ const SkMatrix& matrix,
SkScalar ks,
SkScalar shininess);
@@ -434,8 +434,7 @@
// 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 @@
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 @@
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 @@
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 @@
}
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
SkIRect bounds;
src.getBounds(&bounds);
- if (!this->applyCropRect(&bounds)) {
+ if (!this->applyCropRect(&bounds, ctm)) {
return false;
}
@@ -881,16 +915,18 @@
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 @@
}
#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 @@
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 @@
SkIRect bounds;
src.getBounds(&bounds);
- if (!this->applyCropRect(&bounds)) {
+ if (!this->applyCropRect(&bounds, ctm)) {
return false;
}
@@ -958,15 +994,16 @@
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 @@
}
#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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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::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 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 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());
diff --git a/src/effects/SkMagnifierImageFilter.cpp b/src/effects/SkMagnifierImageFilter.cpp
index a747620..aa91b1c 100644
--- a/src/effects/SkMagnifierImageFilter.cpp
+++ b/src/effects/SkMagnifierImageFilter.cpp
@@ -215,7 +215,7 @@
SkIntToScalar(width), SkIntToScalar(height)),
inset));
GrEffectRef* effect;
- filter->asNewEffect(&effect, textures[0], SkIPoint::Make(0, 0));
+ filter->asNewEffect(&effect, textures[0], SkMatrix::I());
SkASSERT(NULL != effect);
return effect;
}
@@ -261,7 +261,7 @@
}
#if SK_SUPPORT_GPU
-bool SkMagnifierImageFilter::asNewEffect(GrEffectRef** effect, GrTexture* texture, const SkIPoint&) const {
+bool SkMagnifierImageFilter::asNewEffect(GrEffectRef** effect, GrTexture* texture, const SkMatrix&) const {
if (effect) {
*effect = GrMagnifierEffect::Create(texture,
fSrcRect.x() / texture->width(),
diff --git a/src/effects/SkMatrixConvolutionImageFilter.cpp b/src/effects/SkMatrixConvolutionImageFilter.cpp
index 1f60a49..37ca2fa 100644
--- a/src/effects/SkMatrixConvolutionImageFilter.cpp
+++ b/src/effects/SkMatrixConvolutionImageFilter.cpp
@@ -561,7 +561,7 @@
bool SkMatrixConvolutionImageFilter::asNewEffect(GrEffectRef** effect,
GrTexture* texture,
- const SkIPoint&) const {
+ const SkMatrix&) const {
if (!effect) {
return fKernelSize.width() * fKernelSize.height() <= MAX_KERNEL_SIZE;
}
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index ccb8311..f77fdf7 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1476,7 +1476,9 @@
SkBitmap filteredBitmap;
if (NULL != filter) {
- if (filter_texture(this, fContext, texture, filter, w, h, SkMatrix::I(), &filteredBitmap,
+ SkMatrix matrix(*draw.fMatrix);
+ matrix.postTranslate(SkIntToScalar(-left), SkIntToScalar(-top));
+ if (filter_texture(this, fContext, texture, filter, w, h, matrix, &filteredBitmap,
&offset)) {
texture = (GrTexture*) filteredBitmap.getTexture();
w = filteredBitmap.width();
@@ -1563,7 +1565,9 @@
if (NULL != filter) {
SkIPoint offset = SkIPoint::Make(0, 0);
- if (filter_texture(this, fContext, devTex, filter, w, h, SkMatrix::I(), &filteredBitmap,
+ SkMatrix matrix(*draw.fMatrix);
+ matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y));
+ if (filter_texture(this, fContext, devTex, filter, w, h, matrix, &filteredBitmap,
&offset)) {
devTex = filteredBitmap.getTexture();
w = filteredBitmap.width();