Further cleanup in FilterEffectRenderer.

Change FilterEffectRenderer not to be a subclass of Filter anymore, and instantiate a ReferenceFilter as a parent for all shorthand filters instead. Remove FilterEffectRendererHelper entirely, and put its remaining functionality into FilterEffectRenderer.

Replace the AffineTransform in Filter with a float scale parameter, since that's all it does now anyway. Note that applyHorizontal/VerticalScale() still need to remain separate, since SVGFilter applies further, possibly non-uniform scaling in its overrides of those functions.

prepareFilterEffect() and beginFilterEffect() have been merged. This removes an incorrect early-out, which fixes http://crbug.com/254449.

BUG=240827,254449

Review URL: https://codereview.chromium.org/644713004

git-svn-id: svn://svn.chromium.org/blink/trunk@183676 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent d55d11a6
...@@ -638,6 +638,7 @@ crbug.com/326524 virtual/threaded/compositing/visibility/visibility-simple-video ...@@ -638,6 +638,7 @@ crbug.com/326524 virtual/threaded/compositing/visibility/visibility-simple-video
crbug.com/342574 fast/css-generated-content/crash-selection-editing-removes-pseudo.html [ Crash ] crbug.com/342574 fast/css-generated-content/crash-selection-editing-removes-pseudo.html [ Crash ]
crbug.com/346151 css3/filters/effect-reference-hidpi-hw.html [ Pass ImageOnlyFailure ] crbug.com/346151 css3/filters/effect-reference-hidpi-hw.html [ Pass ImageOnlyFailure ]
crbug.com/254449 css3/filters/effect-reference-tile.html [ NeedsRebaseline ]
crbug.com/337732 fast/css/fontfaceset-download-error.html [ Pass Timeout ] crbug.com/337732 fast/css/fontfaceset-download-error.html [ Pass Timeout ]
......
...@@ -253,7 +253,7 @@ void LayerPainter::paintLayerContents(GraphicsContext* context, const LayerPaint ...@@ -253,7 +253,7 @@ void LayerPainter::paintLayerContents(GraphicsContext* context, const LayerPaint
beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, paintingInfo.paintBehavior); beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, paintingInfo.paintBehavior);
LayerPaintingInfo localPaintingInfo(paintingInfo); LayerPaintingInfo localPaintingInfo(paintingInfo);
FilterEffectRendererHelper filterPainter(m_renderLayer.filterRenderer() && m_renderLayer.paintsWithFilters()); bool haveFilterEffect = m_renderLayer.filterRenderer() && m_renderLayer.paintsWithFilters();
LayerFragments layerFragments; LayerFragments layerFragments;
if (shouldPaintContent || shouldPaintOutline || isPaintingOverlayScrollbars) { if (shouldPaintContent || shouldPaintOutline || isPaintingOverlayScrollbars) {
...@@ -265,34 +265,29 @@ void LayerPainter::paintLayerContents(GraphicsContext* context, const LayerPaint ...@@ -265,34 +265,29 @@ void LayerPainter::paintLayerContents(GraphicsContext* context, const LayerPaint
updatePaintingInfoForFragments(layerFragments, localPaintingInfo, paintFlags, shouldPaintContent, &offsetFromRoot); updatePaintingInfoForFragments(layerFragments, localPaintingInfo, paintFlags, shouldPaintContent, &offsetFromRoot);
} }
if (filterPainter.haveFilterEffect()) { if (haveFilterEffect) {
ASSERT(m_renderLayer.filterInfo()); ASSERT(m_renderLayer.filterInfo());
if (!rootRelativeBoundsComputed) if (!rootRelativeBoundsComputed)
rootRelativeBounds = m_renderLayer.physicalBoundingBoxIncludingReflectionAndStackingChildren(paintingInfo.rootLayer, offsetFromRoot); rootRelativeBounds = m_renderLayer.physicalBoundingBoxIncludingReflectionAndStackingChildren(paintingInfo.rootLayer, offsetFromRoot);
if (filterPainter.prepareFilterEffect(&m_renderLayer, rootRelativeBounds, paintingInfo.paintDirtyRect)) { // Do transparency and clipping before starting filter processing.
if (haveTransparency) {
// Do transparency and clipping before starting filter processing. // If we have a filter and transparency, we have to eagerly start a transparency layer here, rather than risk a child layer lazily starts one after filter processing.
if (haveTransparency) { beginTransparencyLayers(context, localPaintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, localPaintingInfo.paintBehavior);
// If we have a filter and transparency, we have to eagerly start a transparency layer here, rather than risk a child layer lazily starts one after filter processing. }
beginTransparencyLayers(context, localPaintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, localPaintingInfo.paintBehavior); // We'll handle clipping to the dirty rect before filter rasterization.
} // Filter processing will automatically expand the clip rect and the offscreen to accommodate any filter outsets.
// We'll handle clipping to the dirty rect before filter rasterization. // FIXME: It is incorrect to just clip to the damageRect here once multiple fragments are involved.
// Filter processing will automatically expand the clip rect and the offscreen to accommodate any filter outsets. ClipRect backgroundRect = layerFragments.isEmpty() ? ClipRect() : layerFragments[0].backgroundRect;
// FIXME: It is incorrect to just clip to the damageRect here once multiple fragments are involved. clipToRect(localPaintingInfo, context, backgroundRect, paintFlags);
ClipRect backgroundRect = layerFragments.isEmpty() ? ClipRect() : layerFragments[0].backgroundRect; // Subsequent code should not clip to the dirty rect, since we've already
clipToRect(localPaintingInfo, context, backgroundRect, paintFlags); // done it above, and doing it later will defeat the outsets.
// Subsequent code should not clip to the dirty rect, since we've already localPaintingInfo.clipToDirtyRect = false;
// done it above, and doing it later will defeat the outsets. haveFilterEffect = m_renderLayer.filterRenderer()->beginFilterEffect(context, rootRelativeBounds);
localPaintingInfo.clipToDirtyRect = false; if (!haveFilterEffect) {
filterPainter.beginFilterEffect(context); // If the the filter failed to start, undo the clip immediately
restoreClip(context, localPaintingInfo.paintDirtyRect, backgroundRect);
if (!filterPainter.haveFilterEffect()) {
// If the the filter failed to start, undo the clip immediately
restoreClip(context, localPaintingInfo.paintDirtyRect, backgroundRect);
}
} }
} }
...@@ -343,11 +338,11 @@ void LayerPainter::paintLayerContents(GraphicsContext* context, const LayerPaint ...@@ -343,11 +338,11 @@ void LayerPainter::paintLayerContents(GraphicsContext* context, const LayerPaint
if (shouldPaintOverlayScrollbars) if (shouldPaintOverlayScrollbars)
paintOverflowControlsForFragments(layerFragments, context, localPaintingInfo, paintFlags); paintOverflowControlsForFragments(layerFragments, context, localPaintingInfo, paintFlags);
if (filterPainter.haveFilterEffect()) { if (haveFilterEffect) {
// Apply the correct clipping (ie. overflow: hidden). // Apply the correct clipping (ie. overflow: hidden).
// FIXME: It is incorrect to just clip to the damageRect here once multiple fragments are involved. // FIXME: It is incorrect to just clip to the damageRect here once multiple fragments are involved.
ClipRect backgroundRect = layerFragments.isEmpty() ? ClipRect() : layerFragments[0].backgroundRect; ClipRect backgroundRect = layerFragments.isEmpty() ? ClipRect() : layerFragments[0].backgroundRect;
filterPainter.endFilterEffect(context); m_renderLayer.filterRenderer()->endFilterEffect(context);
restoreClip(context, localPaintingInfo.paintDirtyRect, backgroundRect); restoreClip(context, localPaintingInfo.paintDirtyRect, backgroundRect);
} }
......
...@@ -26,67 +26,35 @@ ...@@ -26,67 +26,35 @@
#ifndef FilterEffectRenderer_h #ifndef FilterEffectRenderer_h
#define FilterEffectRenderer_h #define FilterEffectRenderer_h
#include "core/svg/graphics/filters/SVGFilterBuilder.h"
#include "platform/geometry/FloatRect.h"
#include "platform/geometry/IntRectExtent.h"
#include "platform/geometry/LayoutRect.h"
#include "platform/graphics/ImageBuffer.h"
#include "platform/graphics/filters/Filter.h"
#include "platform/graphics/filters/FilterEffect.h" #include "platform/graphics/filters/FilterEffect.h"
#include "platform/graphics/filters/FilterOperations.h"
#include "platform/graphics/filters/SourceGraphic.h"
#include "wtf/PassRefPtr.h" #include "wtf/PassRefPtr.h"
#include "wtf/RefCounted.h" #include "wtf/RefCounted.h"
#include "wtf/RefPtr.h" #include "wtf/RefPtr.h"
#include "wtf/Vector.h"
namespace blink { namespace blink {
class FilterOperations;
class FloatRect;
class GraphicsContext; class GraphicsContext;
class ReferenceFilter; class ReferenceFilter;
class RenderLayer;
class RenderObject; class RenderObject;
class FilterEffectRendererHelper { class FilterEffectRenderer final : public RefCounted<FilterEffectRenderer>
public:
FilterEffectRendererHelper(bool haveFilterEffect)
: m_renderLayer(0)
, m_haveFilterEffect(haveFilterEffect)
{
}
bool haveFilterEffect() const { return m_haveFilterEffect; }
bool prepareFilterEffect(RenderLayer*, const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect);
void beginFilterEffect(GraphicsContext*);
void endFilterEffect(GraphicsContext*);
private:
RenderLayer* m_renderLayer;
FloatRect m_filterBoxRect;
bool m_haveFilterEffect;
};
class FilterEffectRenderer final : public Filter
{ {
WTF_MAKE_FAST_ALLOCATED; WTF_MAKE_FAST_ALLOCATED;
public: public:
virtual ~FilterEffectRenderer();
static PassRefPtr<FilterEffectRenderer> create() static PassRefPtr<FilterEffectRenderer> create()
{ {
return adoptRef(new FilterEffectRenderer()); return adoptRef(new FilterEffectRenderer());
} }
void setSourceImageRect(const IntRect& sourceImageRect)
{
m_sourceDrawingRegion = sourceImageRect;
}
virtual IntRect sourceImageRect() const override { return m_sourceDrawingRegion; }
bool build(RenderObject* renderer, const FilterOperations&); bool build(RenderObject* renderer, const FilterOperations&);
void updateBackingStoreRect(const FloatRect& filterRect); bool beginFilterEffect(GraphicsContext*, const FloatRect& filterBoxRect);
void endFilterEffect(GraphicsContext*);
void clearIntermediateResults(); void clearIntermediateResults();
LayoutRect computeSourceImageRectForDirtyRect(const LayoutRect& dirtyRect);
PassRefPtr<FilterEffect> lastEffect() const PassRefPtr<FilterEffect> lastEffect() const
{ {
return m_lastEffect; return m_lastEffect;
...@@ -94,11 +62,7 @@ public: ...@@ -94,11 +62,7 @@ public:
private: private:
FilterEffectRenderer(); FilterEffectRenderer();
virtual ~FilterEffectRenderer();
IntRect m_sourceDrawingRegion;
RefPtr<SourceGraphic> m_sourceGraphic;
RefPtr<FilterEffect> m_lastEffect; RefPtr<FilterEffect> m_lastEffect;
Vector<RefPtr<ReferenceFilter> > m_referenceFilters; Vector<RefPtr<ReferenceFilter> > m_referenceFilters;
}; };
......
...@@ -2714,9 +2714,7 @@ FilterOperations RenderLayer::computeFilterOperations(const RenderStyle* style) ...@@ -2714,9 +2714,7 @@ FilterOperations RenderLayer::computeFilterOperations(const RenderStyle* style)
continue; continue;
ReferenceFilterOperation* referenceOperation = toReferenceFilterOperation(filterOperation); ReferenceFilterOperation* referenceOperation = toReferenceFilterOperation(filterOperation);
// FIXME: Cache the ReferenceFilter if it didn't change. // FIXME: Cache the ReferenceFilter if it didn't change.
RefPtr<ReferenceFilter> referenceFilter = ReferenceFilter::create(); RefPtr<ReferenceFilter> referenceFilter = ReferenceFilter::create(style->effectiveZoom());
float zoom = style->effectiveZoom();
referenceFilter->setAbsoluteTransform(AffineTransform().scale(zoom, zoom));
referenceFilter->setLastEffect(ReferenceFilterBuilder::build(referenceFilter.get(), renderer(), referenceFilter->sourceGraphic(), referenceFilter->setLastEffect(ReferenceFilterBuilder::build(referenceFilter.get(), renderer(), referenceFilter->sourceGraphic(),
referenceOperation)); referenceOperation));
referenceOperation->setFilter(referenceFilter.release()); referenceOperation->setFilter(referenceFilter.release());
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
namespace blink { namespace blink {
SVGFilter::SVGFilter(const IntRect& absoluteSourceDrawingRegion, const FloatRect& targetBoundingBox, const FloatRect& filterRegion, bool effectBBoxMode) SVGFilter::SVGFilter(const IntRect& absoluteSourceDrawingRegion, const FloatRect& targetBoundingBox, const FloatRect& filterRegion, bool effectBBoxMode)
: Filter(AffineTransform()) : Filter(1.0f)
, m_absoluteSourceDrawingRegion(absoluteSourceDrawingRegion) , m_absoluteSourceDrawingRegion(absoluteSourceDrawingRegion)
, m_targetBoundingBox(targetBoundingBox) , m_targetBoundingBox(targetBoundingBox)
, m_effectBBoxMode(effectBBoxMode) , m_effectBBoxMode(effectBBoxMode)
......
...@@ -137,9 +137,8 @@ SkShader* FETurbulence::createShader() ...@@ -137,9 +137,8 @@ SkShader* FETurbulence::createShader()
// and not the target bounding box scale (as SVGFilter::apply*Scale() // and not the target bounding box scale (as SVGFilter::apply*Scale()
// would do). Note also that we divide by the scale since this is // would do). Note also that we divide by the scale since this is
// a frequency, not a period. // a frequency, not a period.
const AffineTransform& absoluteTransform = filter()->absoluteTransform(); float baseFrequencyX = m_baseFrequencyX / filter()->scale();
float baseFrequencyX = m_baseFrequencyX / absoluteTransform.a(); float baseFrequencyY = m_baseFrequencyY / filter()->scale();
float baseFrequencyY = m_baseFrequencyY / absoluteTransform.d();
return (type() == FETURBULENCE_TYPE_FRACTALNOISE) ? return (type() == FETURBULENCE_TYPE_FRACTALNOISE) ?
SkPerlinNoiseShader::CreateFractalNoise(SkFloatToScalar(baseFrequencyX), SkPerlinNoiseShader::CreateFractalNoise(SkFloatToScalar(baseFrequencyX),
SkFloatToScalar(baseFrequencyY), numOctaves(), SkFloatToScalar(seed()), SkFloatToScalar(baseFrequencyY), numOctaves(), SkFloatToScalar(seed()),
......
...@@ -30,39 +30,16 @@ namespace blink { ...@@ -30,39 +30,16 @@ namespace blink {
class PLATFORM_EXPORT Filter : public RefCounted<Filter> { class PLATFORM_EXPORT Filter : public RefCounted<Filter> {
public: public:
Filter(const AffineTransform& absoluteTransform) Filter(float scale)
: m_absoluteTransform(absoluteTransform) : m_scale(scale) { }
, m_inverseTransform(absoluteTransform.inverse())
{
// Filters can only accept scaling and translating transformations, as coordinates
// in most primitives are given in horizontal and vertical directions.
ASSERT(!absoluteTransform.b() && !absoluteTransform.c());
}
virtual ~Filter() { } virtual ~Filter() { }
const AffineTransform& absoluteTransform() const { return m_absoluteTransform; } float scale() const { return m_scale; }
FloatRect mapLocalRectToAbsoluteRect(const FloatRect& rect) const { FloatRect result(rect); result.scale(m_scale); return result; }
void setAbsoluteTransform(const AffineTransform& absoluteTransform) FloatRect mapAbsoluteRectToLocalRect(const FloatRect& rect) const { FloatRect result(rect); result.scale(1.0f / m_scale); return result; }
{ virtual float applyHorizontalScale(float value) const { return m_scale * value; }
// Filters can only accept scaling and translating transformations, as coordinates virtual float applyVerticalScale(float value) const { return m_scale * value; }
// in most primitives are given in horizontal and vertical directions.
ASSERT(!absoluteTransform.b() && !absoluteTransform.c());
m_absoluteTransform = absoluteTransform;
m_inverseTransform = absoluteTransform.inverse();
m_absoluteFilterRegion = m_absoluteTransform.mapRect(m_filterRegion);
}
FloatPoint mapAbsolutePointToLocalPoint(const FloatPoint& point) const { return m_inverseTransform.mapPoint(point); }
FloatRect mapLocalRectToAbsoluteRect(const FloatRect& rect) const { return m_absoluteTransform.mapRect(rect); }
FloatRect mapAbsoluteRectToLocalRect(const FloatRect& rect) const { return m_inverseTransform.mapRect(rect); }
virtual float applyHorizontalScale(float value) const
{
return value * m_absoluteTransform.a();
}
virtual float applyVerticalScale(float value) const
{
return value * m_absoluteTransform.d();
}
virtual FloatPoint3D resolve3dPoint(const FloatPoint3D& point) const { return point; } virtual FloatPoint3D resolve3dPoint(const FloatPoint3D& point) const { return point; }
virtual IntRect sourceImageRect() const = 0; virtual IntRect sourceImageRect() const = 0;
...@@ -73,12 +50,12 @@ public: ...@@ -73,12 +50,12 @@ public:
void setFilterRegion(const FloatRect& rect) void setFilterRegion(const FloatRect& rect)
{ {
m_filterRegion = rect; m_filterRegion = rect;
m_absoluteFilterRegion = m_absoluteTransform.mapRect(m_filterRegion); m_absoluteFilterRegion = rect;
m_absoluteFilterRegion.scale(m_scale);
} }
private: private:
AffineTransform m_absoluteTransform; float m_scale;
AffineTransform m_inverseTransform;
FloatRect m_absoluteFilterRegion; FloatRect m_absoluteFilterRegion;
FloatRect m_filterRegion; FloatRect m_filterRegion;
}; };
......
...@@ -260,7 +260,7 @@ SkImageFilter::CropRect FilterEffect::getCropRect(const FloatSize& cropOffset) c ...@@ -260,7 +260,7 @@ SkImageFilter::CropRect FilterEffect::getCropRect(const FloatSize& cropOffset) c
rect.setHeight(boundaries.height()); rect.setHeight(boundaries.height());
flags |= SkImageFilter::CropRect::kHasBottom_CropEdge; flags |= SkImageFilter::CropRect::kHasBottom_CropEdge;
} }
rect.scale(filter()->absoluteTransform().a(), filter()->absoluteTransform().d()); rect.scale(filter()->scale());
return SkImageFilter::CropRect(rect, flags); return SkImageFilter::CropRect(rect, flags);
} }
......
...@@ -42,7 +42,7 @@ protected: ...@@ -42,7 +42,7 @@ protected:
void colorSpaceTest() void colorSpaceTest()
{ {
// Build filter tree // Build filter tree
RefPtr<ReferenceFilter> referenceFilter = ReferenceFilter::create(); RefPtr<ReferenceFilter> referenceFilter = ReferenceFilter::create(1.0f);
// Add a dummy source graphic input // Add a dummy source graphic input
RefPtr<FilterEffect> sourceEffect = referenceFilter->sourceGraphic(); RefPtr<FilterEffect> sourceEffect = referenceFilter->sourceGraphic();
......
...@@ -37,8 +37,8 @@ ...@@ -37,8 +37,8 @@
namespace blink { namespace blink {
ReferenceFilter::ReferenceFilter() ReferenceFilter::ReferenceFilter(float scale)
: Filter(AffineTransform()) : Filter(scale)
, m_sourceGraphic(SourceGraphic::create(this)) , m_sourceGraphic(SourceGraphic::create(this))
{ {
} }
......
...@@ -43,9 +43,9 @@ class FilterEffect; ...@@ -43,9 +43,9 @@ class FilterEffect;
class PLATFORM_EXPORT ReferenceFilter: public Filter { class PLATFORM_EXPORT ReferenceFilter: public Filter {
public: public:
static PassRefPtr<ReferenceFilter> create() static PassRefPtr<ReferenceFilter> create(float scale)
{ {
return adoptRef(new ReferenceFilter()); return adoptRef(new ReferenceFilter(scale));
} }
virtual IntRect sourceImageRect() const override { return IntRect(); }; virtual IntRect sourceImageRect() const override { return IntRect(); };
...@@ -56,7 +56,7 @@ public: ...@@ -56,7 +56,7 @@ public:
SourceGraphic* sourceGraphic() const { return m_sourceGraphic.get(); } SourceGraphic* sourceGraphic() const { return m_sourceGraphic.get(); }
private: private:
ReferenceFilter(); ReferenceFilter(float scale);
virtual ~ReferenceFilter(); virtual ~ReferenceFilter();
RefPtr<SourceGraphic> m_sourceGraphic; RefPtr<SourceGraphic> m_sourceGraphic;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment