aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-08-27 21:37:01 +0000
committerGravatar senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-08-27 21:37:01 +0000
commitfbaea5336690ffc4fd9ee695608e9457da10eeab (patch)
tree1839224ddda0af4fcfd29e42738d90b0f9ed3127
parent9d54db045b7fc605b200a84629f3d57a212203d5 (diff)
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
-rw-r--r--gm/lighting.cpp13
-rw-r--r--include/core/SkImageFilter.h17
-rw-r--r--include/effects/SkMagnifierImageFilter.h2
-rw-r--r--include/effects/SkMatrixConvolutionImageFilter.h2
-rw-r--r--src/core/SkCanvas.cpp9
-rw-r--r--src/core/SkImageFilter.cpp23
-rw-r--r--src/effects/SkBlurImageFilter.cpp4
-rwxr-xr-xsrc/effects/SkColorFilterImageFilter.cpp2
-rw-r--r--src/effects/SkLightingImageFilter.cpp164
-rw-r--r--src/effects/SkMagnifierImageFilter.cpp4
-rw-r--r--src/effects/SkMatrixConvolutionImageFilter.cpp2
-rw-r--r--src/gpu/SkGpuDevice.cpp8
12 files changed, 156 insertions, 94 deletions
diff --git a/gm/lighting.cpp b/gm/lighting.cpp
index f16e781db0..330e0ee5fe 100644
--- a/gm/lighting.cpp
+++ b/gm/lighting.cpp
@@ -44,9 +44,10 @@ protected:
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 @@ protected:
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 01b3e0bca8..7b9dd3217e 100644
--- a/include/core/SkImageFilter.h
+++ b/include/core/SkImageFilter.h
@@ -77,16 +77,18 @@ public:
* 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 @@ protected:
// 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 b5cbd74ab1..31b446f6a5 100644
--- a/include/effects/SkMagnifierImageFilter.h
+++ b/include/effects/SkMagnifierImageFilter.h
@@ -17,7 +17,7 @@ public:
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 71c8938901..b2602fe6f8 100644
--- a/include/effects/SkMatrixConvolutionImageFilter.h
+++ b/include/effects/SkMatrixConvolutionImageFilter.h
@@ -62,7 +62,7 @@ protected:
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 c59cd04016..ff688f5080 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -999,7 +999,9 @@ void SkCanvas::internalDrawDevice(SkDevice* srcDev, int x, int y,
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 @@ void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
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 222a029997..502613bb68 100644
--- a/src/core/SkImageFilter.cpp
+++ b/src/core/SkImageFilter.cpp
@@ -102,7 +102,7 @@ bool SkImageFilter::onFilterImage(Proxy*, const SkBitmap&, const SkMatrix&,
}
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 @@ bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMa
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 @@ bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMa
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 @@ bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMa
#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 @@ bool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
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 4b2d3b88ff..3f97ddd59a 100644
--- a/src/effects/SkBlurImageFilter.cpp
+++ b/src/effects/SkBlurImageFilter.cpp
@@ -158,7 +158,7 @@ bool SkBlurImageFilter::onFilterImage(Proxy* proxy,
SkIRect srcBounds, dstBounds;
src.getBounds(&srcBounds);
- if (!this->applyCropRect(&srcBounds)) {
+ if (!this->applyCropRect(&srcBounds, ctm)) {
return false;
}
@@ -216,7 +216,7 @@ bool SkBlurImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const
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 9c2c54eb56..16a36bb4c1 100755
--- a/src/effects/SkColorFilterImageFilter.cpp
+++ b/src/effects/SkColorFilterImageFilter.cpp
@@ -107,7 +107,7 @@ bool SkColorFilterImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& sourc
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 ccb1dc5127..e71df66e6c 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());
diff --git a/src/effects/SkMagnifierImageFilter.cpp b/src/effects/SkMagnifierImageFilter.cpp
index a747620484..aa91b1c980 100644
--- a/src/effects/SkMagnifierImageFilter.cpp
+++ b/src/effects/SkMagnifierImageFilter.cpp
@@ -215,7 +215,7 @@ GrEffectRef* GrMagnifierEffect::TestCreate(SkMWCRandom* random,
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 @@ SkMagnifierImageFilter::SkMagnifierImageFilter(SkRect srcRect, SkScalar inset)
}
#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 1f60a492b2..37ca2fa141 100644
--- a/src/effects/SkMatrixConvolutionImageFilter.cpp
+++ b/src/effects/SkMatrixConvolutionImageFilter.cpp
@@ -561,7 +561,7 @@ GrEffectRef* GrMatrixConvolutionEffect::TestCreate(SkMWCRandom* random,
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 ccb83111a6..f77fdf70a8 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1476,7 +1476,9 @@ void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
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 @@ void SkGpuDevice::drawDevice(const SkDraw& draw, SkDevice* device,
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();