Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 4b6b2cdc90927388eb93d81906d4af25e7aa79df
https://github.com/WebKit/WebKit/commit/4b6b2cdc90927388eb93d81906d4af25e7aa79df
Author: Nikolas Zimmermann <[email protected]>
Date: 2026-09-02 (Wed, 02 Sep 2026)
Changed paths:
A
LayoutTests/css3/filters/filter-repaint-blur-before-first-paint-expected.txt
A LayoutTests/css3/filters/filter-repaint-blur-before-first-paint.html
A LayoutTests/css3/filters/filter-repaint-blur-canvas-partial-expected.txt
A LayoutTests/css3/filters/filter-repaint-blur-canvas-partial.html
A LayoutTests/css3/filters/filter-repaint-blur-inline-expected.txt
A LayoutTests/css3/filters/filter-repaint-blur-inline.html
A
LayoutTests/css3/filters/filter-repaint-blur-inner-content-change-expected.txt
A LayoutTests/css3/filters/filter-repaint-blur-inner-content-change.html
A
LayoutTests/css3/filters/filter-repaint-blur-nested-non-pixel-moving-filter-expected.html
A
LayoutTests/css3/filters/filter-repaint-blur-nested-non-pixel-moving-filter.html
A
LayoutTests/css3/filters/filter-repaint-blur-nested-pixel-moving-filter-expected.html
A
LayoutTests/css3/filters/filter-repaint-blur-nested-pixel-moving-filter.html
M LayoutTests/fast/repaint/drop-shadow-change-full-repaint-expected.txt
M Source/WebCore/rendering/RenderElement.cpp
M Source/WebCore/rendering/RenderLayer.cpp
M Source/WebCore/rendering/RenderLayer.h
M Source/WebCore/rendering/RenderLayerFilters.cpp
M Source/WebCore/rendering/RenderLayerFilters.h
M Source/WebCore/rendering/RenderObject.cpp
M Source/WebCore/rendering/RenderObject.h
M Source/WebCore/rendering/RenderView.h
M Source/WebCore/rendering/updating/RenderTreeUpdater.cpp
Log Message:
-----------
Content changing inside an element with a blur filter doesn't properly repaint
https://bugs.webkit.org/show_bug.cgi?id=322424
Reviewed by Simon Fraser.
The ticket contains a reduction obtained from YouTube Shorts, when dark
mode + ambient mode is enabled. Around the video a glow effect is
visible, which left stale pixels on our ports while the video was
running.
Testcase:
#glow { position: absolute; left: 50%; top: 50%; width: 380px; height: 660px;
margin: -330px 0 0 -190px; transform: scale(1.8, 1.3);
filter: blur(40px); pointer-events: none; }
#glow canvas { position: absolute; width: 100%; height: 100%; }
<div id="glow">
<canvas id="ca" width="86" height="126"></canvas>
<canvas id="cb" width="86" height="126"></canvas>
</div>
macOS repaints this particular testcase correctly, because #glow ends up
composited as the canvases are composited and the platform layer applies
the blur filter. On GTK/WPE they are not: the canvas backing store size is
86 * 126px, below the minimum area we impose for acceleration
(CanvasBase::shouldAccelerate(), queries
Settings::minimumAccelerated2DContextArea which is 128 * 129 with Skia,
0 elsewhere). Both canvases are drawn in software, into the enclosing layer.
The code path our ports take has a bug since 204269@main: we no longer set
setHasSoftwareFilters() anywhere. RenderObject::containerForRepaint() only looks
for an enclosing filter layer while that flag is set, so it never sees #glow.
The repaint is issued against the root layer of the page instead, and
repaintUsingContainer() never calls
RenderLayer::setFilterBackendNeedsRepaintingInRect().
That is the only place that expands the repaint rect by filterOutsets() and was
missing for us.
Instead of bringing back the setHasSoftwareFilters() mechanism, mimic
the outline counter concept: count the renderers with a pixel moving
filter, and maintain the count properly, instead of keeping a flag on all
the time as it used to be in the past.
Furthermore a stale-repaint-rect issue had to be fixed: RenderLayer caches its
repaint container in m_repaintContainer, together with the repaint rects that
are expressed relative to that container. Whether a layer is the repaint
container for its subtree now depends on requiresFullLayerImageForFilters(),
so removing a pixel moving filter, or turning it into a non-pixel-moving filter,
leaves every layer in the subtree pointing at a container that is no longer
a repaint container. That hits an assertion in imported/w3c/web-platform-tests/
css/filter-effects/animation/filter-interpolation-003.html.
This fixes the repainting logic in general, whenever software-rendered
filters are involved, also on Mac platforms as several new testcases
demonstrate.
Tests: css3/filters/filter-repaint-blur-before-first-paint.html
css3/filters/filter-repaint-blur-canvas-partial.html
css3/filters/filter-repaint-blur-inline.html
css3/filters/filter-repaint-blur-inner-content-change.html
css3/filters/filter-repaint-blur-nested-non-pixel-moving-filter.html
css3/filters/filter-repaint-blur-nested-pixel-moving-filter.html
* LayoutTests/css3/filters/filter-repaint-blur-before-first-paint-expected.txt:
Added.
* LayoutTests/css3/filters/filter-repaint-blur-before-first-paint.html: Added.
* LayoutTests/css3/filters/filter-repaint-blur-canvas-partial-expected.txt:
Added.
* LayoutTests/css3/filters/filter-repaint-blur-canvas-partial.html: Added.
* LayoutTests/css3/filters/filter-repaint-blur-inline-expected.txt: Added.
* LayoutTests/css3/filters/filter-repaint-blur-inline.html: Added.
*
LayoutTests/css3/filters/filter-repaint-blur-inner-content-change-expected.txt:
Added.
* LayoutTests/css3/filters/filter-repaint-blur-inner-content-change.html: Added.
*
LayoutTests/css3/filters/filter-repaint-blur-nested-non-pixel-moving-filter-expected.html:
Added.
*
LayoutTests/css3/filters/filter-repaint-blur-nested-non-pixel-moving-filter.html:
Added.
*
LayoutTests/css3/filters/filter-repaint-blur-nested-pixel-moving-filter-expected.html:
Added.
* LayoutTests/css3/filters/filter-repaint-blur-nested-pixel-moving-filter.html:
Added.
* LayoutTests/fast/repaint/drop-shadow-change-full-repaint-expected.txt:
The first repaint rect dumped was wrong, this fixes it as side-effect.
* Source/WebCore/rendering/RenderElement.cpp:
(WebCore::RenderElement::styleWillChange):
(WebCore::RenderElement::willBeDestroyed):
* Source/WebCore/rendering/RenderLayer.cpp:
(WebCore::RenderLayer::removeOnlyThisLayer):
(WebCore::RenderLayer::shouldPaintWithFilters const):
(WebCore::RenderLayer::requiresFullLayerImageForFilters const):
(WebCore::RenderLayer::updateRepaintRectsIncludingDescendants):
(WebCore::RenderLayer::computeRepaintRectsIncludingDescendants): Deleted,
folded into the above.
(WebCore::RenderLayer::compositingStatusChanged):
(WebCore::RenderLayer::enclosingPixelMovingFilterLayer const):
(WebCore::RenderLayer::setFilterBackendNeedsRepaintingInRect):
(WebCore::RenderLayer::updateFiltersAfterStyleChange):
(WebCore::RenderLayer::filterOutsets const):
* Source/WebCore/rendering/RenderLayer.h:
* Source/WebCore/rendering/RenderLayerFilters.cpp:
(WebCore::RenderLayerFilters::isIdentity): Deleted.
* Source/WebCore/rendering/RenderLayerFilters.h:
* Source/WebCore/rendering/RenderObject.cpp:
(WebCore::RenderObject::containerForRepaint const):
(WebCore::RenderObject::repaintUsingContainer const):
(WebCore::RenderObject::issueRepaint const):
(WebCore::RenderObject::repaintSlowRepaintObject const):
* Source/WebCore/rendering/RenderObject.h:
* Source/WebCore/rendering/RenderView.h:
* Source/WebCore/rendering/updating/RenderTreeUpdater.cpp:
(WebCore::repaintAndMarkContainingBlockDirtyBeforeTearDown):
Canonical link: https://commits.webkit.org/320398@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications