[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