[CSS Filters] Filter outsets clipped on composited layers when filter is applied after first layout
https://bugs.webkit.org/show_bug.cgi?id=109098
Reviewed by Dean Jackson.
Source/WebCore:
This patch addresses the following issues:
(1) Compositors who can compute their own filter outsets don't need WebKit to inflate the
composited layer bounds. Eventually, all platforms' compositors should be able to
compute their own filter outsets.
(2) When filter outsets change, we need to update composited layer bounds if the filters are
painted in software.
(3) When filter outsets change, we need to recompute the overlap map to promote the correct
layers to composited layers on all platforms.
Tests: css3/filters/composited-layer-bounds-after-sw-blur-animation.html
css3/filters/composited-layer-bounds-with-composited-blur.html
css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change.html
css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow.html
css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow.html
* platform/graphics/IntRectExtent.h:
(WebCore::IntRectExtent::isZero):
(IntRectExtent):
Make isZero public on IntRectExtent.
* rendering/RenderLayer.cpp:
(WebCore::hasOrHadFilters):
Helper function used to exit early from filters related code.
(WebCore::RenderLayer::updateFilters):
Move filter updating code from RenderLayer::styleChanged into this new method.
This method calls RenderLayerBacking::updateFilters instead of
RenderLayerBacking::updateGraphicsLayerGeometry. RenderLayerBacking::updateFilters lets
us know whether there was a filter paint mode change (i.e. the filters were painted in
software and are now painted in the compositor, or vice-versa). We need to know this
earlier, in RenderLayer::styleChanged, because we may need to rebuild the compositing
layers due to a filter paint mode change.
(WebCore::RenderLayer::styleChanged):
Add a condition for filters for setCompositingLayersNeedRebuild. If the filter outsets
on a layer changed, we need to rebuild the compositing layers because there could be new
overlap. Likewise, if there are or were filter outsets and the filter paint mode changed
the layer bounds (and child positions) may have changed. In either case, we don't
rebuild the compositing layers if there is an accelerated filter animation running.
Remove old code to detect a filter paint mode change from the end of
RenderLayer::styleChanged because it could never be executed. The old code counted on
RenderLayerBacking::canCompositeFilters to change on its own, but it doesn't change
unless updateFilters gets called. Thus, we could never enter the if statement that
calls setBackingNeedsRepaint.
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::updateFilters):
Now return true if there was a filter paint mode change, so RenderLayer::styleChanged
can decide if it should rebuild the compositing layers.
Call updateOrRemoveFilterEffectRenderer and setContentsNeedDisplay if there was a
render mode change. We need to either destroy or create the software renderer and we
need to repaint the layer contents if there was a render mode change.
(WebCore::RenderLayerBacking::updateGraphicsLayerGeometry):
Don't call updateFilters here. Call it earlier in RenderLayer::styleChanged, for reasons
explained above.
* rendering/RenderLayerBacking.h:
(RenderLayerBacking):
Make updateFilters public so RenderLayer::styleChanged can call it.
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::calculateCompositedBounds):
If the platform's compositor computes filter outsets for its layers internally, do not
inflate WebKit's composited bounds for filter outsets. This results in smaller layers
on Safari. Note that we still need to include filter outsets in layer bounds for other
situations like overlap testing in WebKit and when we're painting filters in software.
Source/WTF:
* wtf/Platform.h:
Add flag for HAVE(COMPOSITOR_FILTER_OUTSETS) macro. This is used to check if a
platform's compositor expands layers internally for filter outsets when it applies
filters like drop-shadow and blur. Currently, only CoreAnimation does has this
capability.
LayoutTests:
* compositing/filters/sw-layer-overlaps-hw-shadow-expected.txt:
* compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow-expected.txt:
* compositing/filters/sw-shadow-overlaps-hw-layer-expected.txt:
* compositing/filters/sw-shadow-overlaps-hw-shadow-expected.txt:
The above tests needed rebaselining because we're now using smaller layers on Safari.
We aren't inflating layers for filter outsets since CoreAnimation does it for us
already.
* css3/filters/composited-layer-bounds-after-sw-blur-animation-expected.txt: Added.
* css3/filters/composited-layer-bounds-after-sw-blur-animation.html: Added.
* css3/filters/composited-layer-bounds-with-composited-blur-expected.txt: Added.
* css3/filters/composited-layer-bounds-with-composited-blur.html: Added.
* css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change-expected.txt: Added.
* css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change.html: Added.
* css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt: Added.
* css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow.html: Added.
* css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt: Added.
* css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow.html: Added.
The above tests are all new. They mostly test edge cases with filter render mode
changes, filter outset changes, and composited layer promotion due to overlap.
Before this patch, composited-layer-bounds-after-sw-blur-animation.html breaks
visibly on Safari WebKit nightly. The blur filter in the test appears clipped before
this patch. The other tests render the same before and after this patch, but now their
layer sizes are smaller.
* css3/filters/filter-change-repaint-composited-expected.png:
* css3/filters/filter-change-repaint-composited.html:
This test has been expanded with two more cases, including the original reproduction of
this bug. The test needs rebaselining on Chromium Linux and Win.
* platform/chromium-win/css3/filters/filter-change-repaint-composited-expected.png: Removed.
* platform/chromium/TestExpectations:
* platform/chromium/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow-expected.txt: Added.
* platform/chromium/compositing/filters/sw-shadow-overlaps-hw-shadow-expected.txt: Added.
* platform/chromium/css3/filters/composited-layer-bounds-after-sw-blur-animation-expected.txt: Added.
* platform/chromium/css3/filters/composited-layer-bounds-with-composited-blur-expected.txt: Added.
* platform/chromium/css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change-expected.txt: Added.
* platform/chromium/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt: Added.
* platform/chromium/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt: Added.
We need different expectations for Chromium for the new tests because layer bounds
include filter outsets on Chromium but not on Safari.
* platform/chromium/css3/filters/filter-change-repaint-composited-expected.png: Added.
* platform/qt/TestExpectations:
Note that we need baselines on Qt for the new and updated tests.
git-svn-id: svn://svn.chromium.org/blink/trunk@147502 bbb929c8-8fbe-4397-9dbb-9b2b20218538
38 files changed