WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
68472
Move/copy/merge SVG filter rendering code to generic rendering
https://bugs.webkit.org/show_bug.cgi?id=68472
Summary
Move/copy/merge SVG filter rendering code to generic rendering
Dean Jackson
Reported
2011-09-20 14:09:39 PDT
This will allow filter operations to render HTML elements.
Attachments
Patch
(64.62 KB, patch)
2011-10-19 16:29 PDT
,
Dean Jackson
simon.fraser
: review-
Details
Formatted Diff
Diff
Patch
(35.22 KB, patch)
2011-11-08 17:04 PST
,
Dean Jackson
no flags
Details
Formatted Diff
Diff
Patch
(64.74 KB, patch)
2011-11-09 11:46 PST
,
Dean Jackson
simon.fraser
: review+
Details
Formatted Diff
Diff
Show Obsolete
(2)
View All
Add attachment
proposed patch, testcase, etc.
Radar WebKit Bug Importer
Comment 1
2011-09-20 14:10:34 PDT
<
rdar://problem/10155660
>
Chris Marrin
Comment 2
2011-09-21 13:06:11 PDT
At the moment SVGRenderSupport::prepareToRenderSVGContent and SVGRenderSupport::finishRenderSVGContent are the places that call into the generic filter stuff. This bug is about moving that out to RenderLayer or wherever.
Dean Jackson
Comment 3
2011-10-19 16:29:59 PDT
Created
attachment 111693
[details]
Patch
Simon Fraser (smfr)
Comment 4
2011-10-19 16:53:30 PDT
Comment on
attachment 111693
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=111693&action=review
I think there are two big chunks missing here, and I'm curious about how you plan to implement them: 1. incremental repaints: you need to map a rect through the filter chain. Filters need the ability to say how they affect a given rect. This rect mapping should be used in the repaint code path. 2. How filters expand the visual overflow of an element (also repaint-related).
> Source/WebCore/rendering/RenderFilter.h:44 > +class RenderFilter : public Filter {
I'm not sure that RenderFilter is the best name for this, since it doesn't inherit from RenderObject. Maybe RendererFilter? EffectsFilter?
> Source/WebCore/rendering/RenderFilter.h:52 > + virtual void setSourceImageRect(const FloatRect& sourceImageRect) { m_sourceDrawingRegion = sourceImageRect; } > + virtual FloatRect sourceImageRect() const { return m_sourceDrawingRegion; }
Should these all be LayoutRects?
> Source/WebCore/rendering/RenderFilter.h:57 > + virtual bool effectBoundingBoxMode() const { return false; }
This method has a terrible name. What kind of mode is this?
> Source/WebCore/rendering/RenderLayer.cpp:2696 > + m_filter->setSavedContext(p);
Why does the filter have to know what the original destination context is?
> Source/WebCore/rendering/RenderLayer.cpp:2709 > + p->save(); > + p->concatCTM(transform.toAffineTransform());
I don't really like the save here, and the restore in some other code block a long way below. Can you do what we do for transforms, and call back into paintLayer? Does this filter before or after CSS shadows are applied? Which should it be?
> Source/WebCore/rendering/RenderLayer.cpp:2875 > + p->drawImageBuffer(m_filter->effect()->asImageBuffer(), renderer()->style()->colorSpace(), layerBounds, CompositeSourceOver);
Doesn't the color space need to be passed through the filter chain somehow?
> Source/WebCore/rendering/RenderLayer.cpp:4385 > +void RenderLayer::createFilter() > +{ > + ASSERT(!m_filter); > + m_filter = RenderFilter::create(); > +} > + > +void RenderLayer::removeFilter() > +{ > + m_filter = 0; > +} > +
It's not clear to me that RenderLayer is the right thing to own the filter. Maybe the RenderObject should own it?
> Source/WebCore/rendering/RenderLayer.cpp:4398 > + // For the moment all filter effects are hardcoded to hue-rotate(180deg). > + // See
https://bugs.webkit.org/show_bug.cgi?id=68474
and > + //
https://bugs.webkit.org/show_bug.cgi?id=68475
> + > + RefPtr<SourceGraphic> sourceGraphic = SourceGraphic::create(m_filter.get()); > + m_filter->setSourceGraphic(sourceGraphic); > + Vector<float> inputParameters; > + inputParameters.append(180); > + RefPtr<FEColorMatrix> matrix = FEColorMatrix::create(m_filter.get(), FECOLORMATRIX_TYPE_HUEROTATE, inputParameters); > + matrix->inputEffects().append(sourceGraphic); > + m_filter->setEffect(matrix);
I don't think it's appropriate to check in a hard-coded filter effect.
> Source/WebCore/rendering/RenderObject.h:926 > + bool m_hasFilter : 1;
See comment higher up: // 32 bits have been used here. THERE ARE NO FREE BITS AVAILABLE.
Chris Marrin
Comment 5
2011-10-19 17:02:31 PDT
View in context:
https://bugs.webkit.org/attachment.cgi?id=111693&action=review
Just a few nits. Overall looks good...
> Source/WebCore/rendering/RenderFilter.h:57 > + virtual bool effectBoundingBoxMode() const { return false; }
I'm not sure what this mode does. Maybe a comment?
> Source/WebCore/rendering/RenderFilter.h:69 > + RenderFilter();
Don't at least some compilers require an explicit virtual dtor if you have virtual methods?
> Source/WebCore/rendering/RenderInline.cpp:127 > + setHasReflection(false);
What's the diff here?
> Source/WebCore/rendering/RenderLayer.cpp:4232 > + if (!hasFilter() && m_filter)
I've always disliked testing a variable directly and then using a function to change it. Maybe just get rid of the "&& m_filter" and do and early exit from removeFilter() if it's null?"
> Source/WebCore/rendering/RenderLayer.cpp:4235 > + if (!m_filter)
Same here
> Source/WebCore/rendering/RenderLayer.cpp:4388 > + // For the moment all filter effects are hardcoded to hue-rotate(180deg).
This should be a FIXME
> Source/WebCore/rendering/RenderLayer.cpp:4396 > + RefPtr<FEColorMatrix> matrix = FEColorMatrix::create(m_filter.get(), FECOLORMATRIX_TYPE_HUEROTATE, inputParameters);
Does the HueRotate filter expect its angle in degrees? It doesn't allow units?
> Source/WebCore/rendering/RenderLayer.cpp:4411 > + m_filter->setSourceImage(ImageBuffer::create(layoutSize));
It seems odd to set these 4 values here, when all you're doing is updating the value of sourceImageRect. It would be better if you just set sourceImageRect and let it set the other 3.
Dean Jackson
Comment 6
2011-10-19 17:14:20 PDT
(In reply to
comment #4
)
> (From update of
attachment 111693
[details]
) > View in context:
https://bugs.webkit.org/attachment.cgi?id=111693&action=review
> > I think there are two big chunks missing here, and I'm curious about how you plan to implement them: > 1. incremental repaints: you need to map a rect through the filter chain. Filters need the ability to say how they affect a given rect. This rect mapping should be used in the repaint code path.
Yep. We can do that, but obviously not with the patch I submitted. We'll have to get the Filters to tell us what the output region is so we can expand the overflow.
> 2. How filters expand the visual overflow of an element (also repaint-related).
Each filter effect will need to tell us what the output region is for a given input. I think that's easy for the shorthand filters as only blur expands the region and we know by how much. For generic SVG, we'll have a trickier time, and some filters have infinite output (e.g. flood and turbulence).
> > Source/WebCore/rendering/RenderFilter.h:44 > > +class RenderFilter : public Filter { > > I'm not sure that RenderFilter is the best name for this, since it doesn't inherit from RenderObject. Maybe RendererFilter? EffectsFilter?
Good point.
> > > Source/WebCore/rendering/RenderFilter.h:52 > > + virtual void setSourceImageRect(const FloatRect& sourceImageRect) { m_sourceDrawingRegion = sourceImageRect; } > > + virtual FloatRect sourceImageRect() const { return m_sourceDrawingRegion; } > > Should these all be LayoutRects?
Sure.
> > Source/WebCore/rendering/RenderFilter.h:57 > > + virtual bool effectBoundingBoxMode() const { return false; } > > This method has a terrible name. What kind of mode is this?
TBH, I haven't even looked. I'll follow the virtual function and see what it actually does. Maybe it is something we can use.
> > > Source/WebCore/rendering/RenderLayer.cpp:2696 > > + m_filter->setSavedContext(p); > > Why does the filter have to know what the original destination context is?
It doesn't. It should just be a local variable in the paint.
> > > Source/WebCore/rendering/RenderLayer.cpp:2709 > > + p->save(); > > + p->concatCTM(transform.toAffineTransform()); > > I don't really like the save here, and the restore in some other code block a long way below. > > Can you do what we do for transforms, and call back into paintLayer?
OK.
> > Does this filter before or after CSS shadows are applied? Which should it be?
It filters after shadows.
> > > Source/WebCore/rendering/RenderLayer.cpp:2875 > > + p->drawImageBuffer(m_filter->effect()->asImageBuffer(), renderer()->style()->colorSpace(), layerBounds, CompositeSourceOver); > > Doesn't the color space need to be passed through the filter chain somehow?
Yes, but not in this hardcoded patch.
> > > Source/WebCore/rendering/RenderLayer.cpp:4385 > > +void RenderLayer::createFilter() > > +{ > > + ASSERT(!m_filter); > > + m_filter = RenderFilter::create(); > > +} > > + > > +void RenderLayer::removeFilter() > > +{ > > + m_filter = 0; > > +} > > + > > It's not clear to me that RenderLayer is the right thing to own the filter. Maybe the RenderObject should own it?
OK.
> > I don't think it's appropriate to check in a hard-coded filter effect.
I just didn't want to have this patch include the code for building a filter graph. Maybe it could start with only supporting hue-rotate? (or invert, that's an easy enough one)
> > > Source/WebCore/rendering/RenderObject.h:926 > > + bool m_hasFilter : 1; > > See comment higher up: > // 32 bits have been used here. THERE ARE NO FREE BITS AVAILABLE.
Yikes.
Dean Jackson
Comment 7
2011-10-19 17:31:58 PDT
(In reply to
comment #5
)
> View in context:
https://bugs.webkit.org/attachment.cgi?id=111693&action=review
> > Just a few nits. Overall looks good... > > > Source/WebCore/rendering/RenderFilter.h:57 > > + virtual bool effectBoundingBoxMode() const { return false; } > > I'm not sure what this mode does. Maybe a comment?
I don't know what it does either :)
> > > Source/WebCore/rendering/RenderFilter.h:69 > > + RenderFilter(); > > Don't at least some compilers require an explicit virtual dtor if you have virtual methods?
> > > Source/WebCore/rendering/RenderInline.cpp:127 > > + setHasReflection(false); > > What's the diff here?
Spaces at the end of the line that the stylebot was complaining about.
> > > Source/WebCore/rendering/RenderLayer.cpp:4232 > > + if (!hasFilter() && m_filter) > > I've always disliked testing a variable directly and then using a function to change it. Maybe just get rid of the "&& m_filter" and do and early exit from removeFilter() if it's null?"
OK.
> > > Source/WebCore/rendering/RenderLayer.cpp:4235 > > + if (!m_filter) > > Same here > > > Source/WebCore/rendering/RenderLayer.cpp:4388 > > + // For the moment all filter effects are hardcoded to hue-rotate(180deg). > > This should be a FIXME
OK.
> > > Source/WebCore/rendering/RenderLayer.cpp:4396 > > + RefPtr<FEColorMatrix> matrix = FEColorMatrix::create(m_filter.get(), FECOLORMATRIX_TYPE_HUEROTATE, inputParameters); > > Does the HueRotate filter expect its angle in degrees? It doesn't allow units?
Correct.
> > > Source/WebCore/rendering/RenderLayer.cpp:4411 > > + m_filter->setSourceImage(ImageBuffer::create(layoutSize)); > > It seems odd to set these 4 values here, when all you're doing is updating the value of sourceImageRect. It would be better if you just set sourceImageRect and let it set the other 3.
OK
Dean Jackson
Comment 8
2011-11-08 17:02:01 PST
(In reply to
comment #6
)
> > I think there are two big chunks missing here, and I'm curious about how you plan to implement them: > > 1. incremental repaints: you need to map a rect through the filter chain. Filters need the ability to say how they affect a given rect. This rect mapping should be used in the repaint code path. > > Yep. We can do that, but obviously not with the patch I submitted. We'll have to get the Filters to tell us what the output region is so we can expand the overflow.
I don't want to do that in this patch.
> > 2. How filters expand the visual overflow of an element (also repaint-related). > > Each filter effect will need to tell us what the output region is for a given input. I think that's easy for the shorthand filters as only blur expands the region and we know by how much. For generic SVG, we'll have a trickier time, and some filters have infinite output (e.g. flood and turbulence).
Ditto. At the moment we don't change the element dimensions.
> > > +class RenderFilter : public Filter { > > > > I'm not sure that RenderFilter is the best name for this, since it doesn't inherit from RenderObject. Maybe RendererFilter? EffectsFilter?
FilterEffectsRenderer. I bet we'll come up with a better name soon.
> > > + virtual void setSourceImageRect(const FloatRect& sourceImageRect) { m_sourceDrawingRegion = sourceImageRect; } > > > + virtual FloatRect sourceImageRect() const { return m_sourceDrawingRegion; } > > > > Should these all be LayoutRects? > > Sure.
They can't. These are the virtual methods from FilterEffect.
> > Does this filter before or after CSS shadows are applied? Which should it be? > > It filters after shadows.
Right now filtering comes after everything (including outline, shadows, reflections, masking). We'll coordinate on www-style as to where it really should happen.
> > I don't think it's appropriate to check in a hard-coded filter effect. > > I just didn't want to have this patch include the code for building a filter graph. Maybe it could start with only supporting hue-rotate? (or invert, that's an easy enough one)
No longer hardcoded, but it still only supports hue-rotate.
> > > Source/WebCore/rendering/RenderObject.h:926 > > > + bool m_hasFilter : 1; > > > > See comment higher up: > > // 32 bits have been used here. THERE ARE NO FREE BITS AVAILABLE. > > Yikes.
Moved this to a method on RenderStyle.
Dean Jackson
Comment 9
2011-11-08 17:04:24 PST
Created
attachment 114179
[details]
Patch
Dean Jackson
Comment 10
2011-11-09 11:46:16 PST
Created
attachment 114331
[details]
Patch
Simon Fraser (smfr)
Comment 11
2011-11-09 16:18:50 PST
Comment on
attachment 114331
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=114331&action=review
> Source/WebCore/WebCore.vcproj/WebCore.vcproj:33261 > + ExcludedFromBuild="true"
I don't think you want this here.
> Source/WebCore/rendering/FilterEffectRenderer.h:69 > + virtual void setSourceGraphic(PassRefPtr<SourceGraphic> sourceGraphic) { m_sourceGraphic = sourceGraphic; } > + virtual RefPtr<SourceGraphic> sourceGraphic() const { return m_sourceGraphic; }
I don't get why the input isn't an ImageBuffer, but that's just me.
> Source/WebCore/rendering/RenderLayer.cpp:2691 > + GraphicsContext* sourceGraphicsContext = m_filter->sourceImage()->context();
This all seems rather weird. I filed
bug 71962
.
> Source/WebCore/rendering/RenderLayer.cpp:2693 > + FloatRect paintRect = FloatRect(0, 0, size().width(), size().height());
FloatRect paintRect(FloatPoint(), size()). Should this be in LayoutRects?
> Source/WebCore/rendering/RenderLayer.cpp:2706 > + LayoutRect filterBounds = LayoutRect(layerOrigin.x(), layerOrigin.y(), size().width(), size().height());
filterBounds(layerOrigin(), size())?
> Source/WebCore/rendering/RenderLayer.cpp:2709 > + p->drawImageBuffer(m_filter->effect()->asImageBuffer(), renderer()->style()->colorSpace(), filterBounds, CompositeSourceOver);
Should we clear the filter here? Does that throw away buffers?
> Source/WebCore/rendering/RenderLayer.cpp:4244 > + if (hasFilter()) > + updateFilterEffect();
You could have updateFilterEffect() just do the hasFilter() test.
> Source/WebCore/rendering/RenderLayer.cpp:4393 > + // For the moment we only support a single hue-rotate() filter. > + // See
https://bugs.webkit.org/show_bug.cgi?id=68474
and > + //
https://bugs.webkit.org/show_bug.cgi?id=68475
> + > + RefPtr<FilterEffect> effect; > + FilterOperations filterOperations = renderer()->style()->filter();
It would be nice to be able to optimize this to do nothing if the filter style hasn't changed.
> Source/WebCore/rendering/RenderLayer.cpp:4416 > +void RenderLayer::updateFilterBackingStore() > +{
Seems pretty bogus to have to do this every time. Maybe covered by
bug 71962
.
> LayoutTests/css3/filters/add-filter-rendering-expected.txt:9 > + text run at (0,0) width 572: "This paragraph will have a filter applied. Once applied, it should have a green background."
Try to avoid text in pixel results. You could put the text in an HTML comment.
Dean Jackson
Comment 12
2011-11-10 13:36:45 PST
(In reply to
comment #11
)
> (From update of
attachment 114331
[details]
) > View in context:
https://bugs.webkit.org/attachment.cgi?id=114331&action=review
> > > Source/WebCore/WebCore.vcproj/WebCore.vcproj:33261 > > + ExcludedFromBuild="true" > > I don't think you want this here.
I added the file to the AllInOne when committing, so left this in.
> > Source/WebCore/rendering/RenderLayer.cpp:2693 > > + FloatRect paintRect = FloatRect(0, 0, size().width(), size().height()); > > FloatRect paintRect(FloatPoint(), size()). > Should this be in LayoutRects?
The filter code expects FloatRects.
> You could have updateFilterEffect() just do the hasFilter() test.
Done
> It would be nice to be able to optimize this to do nothing if the filter style hasn't changed.
Yeah.
> Try to avoid text in pixel results. You could put the text in an HTML comment.
Done.
Dean Jackson
Comment 13
2011-11-10 13:37:01 PST
http://trac.webkit.org/changeset/99893
Nikolas Zimmermann
Comment 14
2011-11-10 13:59:53 PST
Comment on
attachment 114331
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=114331&action=review
Nice start Dean! Just a quick note regarding the Filter class:
> Source/WebCore/rendering/FilterEffectRenderer.h:63 > + virtual bool effectBoundingBoxMode() const { return false; }
I removed this today from Filter.h, you can remove this function.
Dean Jackson
Comment 15
2011-11-10 14:16:17 PST
(In reply to
comment #14
)
> (From update of
attachment 114331
[details]
) > View in context:
https://bugs.webkit.org/attachment.cgi?id=114331&action=review
> > Nice start Dean! Just a quick note regarding the Filter class:
Small steps, but we'll get there.
> > Source/WebCore/rendering/FilterEffectRenderer.h:63 > > + virtual bool effectBoundingBoxMode() const { return false; } > > I removed this today from Filter.h, you can remove this function.
Excellent. I'll do that. Dean
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug