Skip to content

Commit b70eabc

Browse files
committed
Avoid scheduling rendering updates for SVG animations on elements
without renderers https://bugs.webkit.org/show_bug.cgi?id=298217 rdar://159647563 Reviewed by Antoine Quint. When SVG elements with SMIL animations (like animateTransform) are inside containers with hidden attribute, the legacy SVG engine was scheduling full page rendering updates every animation frame despite the elements having no renderer. Now when animations run on elements without renderers, we skip scheduling rendering updates entirely. * LayoutTests/svg/animations/animateTransform-hidden-no-rendering-updates-expected.txt: Added. * LayoutTests/svg/animations/animateTransform-hidden-no-rendering-updates.html: Added. * Source/WebCore/svg/SVGGraphicsElement.cpp: (WebCore::SVGGraphicsElement::svgAttributeChanged): Canonical link: https://commits.webkit.org/304744@main
1 parent 05fad69 commit b70eabc

File tree

3 files changed

+82
-2
lines changed

3 files changed

+82
-2
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Test that SVG animations on hidden elements do not trigger rendering updates.
2+
3+
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
4+
5+
6+
PASS updateCount <= 5 is true
7+
PASS successfullyParsed is true
8+
9+
TEST COMPLETE
10+
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<!DOCTYPE HTML>
2+
<html>
3+
4+
<head>
5+
<script src="../../resources/js-test.js"></script>
6+
<style>
7+
#container {
8+
width: 100px;
9+
height: 100px;
10+
}
11+
</style>
12+
</head>
13+
14+
<body>
15+
<div id="container" hidden>
16+
<svg viewBox="0 0 100 100" width="100" height="100">
17+
<circle cx="50" cy="50" fill="none" r="35" stroke="currentColor"
18+
stroke-dasharray="164.93361431346415 56.97787143782138" stroke-width="6">
19+
<animateTransform attributeName="transform" type="rotate" repeatCount="indefinite" dur="1s"
20+
values="0 50 50;90 50 50;180 50 50;360 50 50" keyTimes="0;0.40;0.65;1"></animateTransform>
21+
</circle>
22+
</svg>
23+
</div>
24+
<div id="console"></div>
25+
<script>
26+
window.jsTestIsAsync = true;
27+
28+
let updateCount = 0;
29+
30+
function sleepFor(duration) {
31+
return new Promise(resolve => setTimeout(resolve, duration));
32+
}
33+
34+
async function waitForRenderingUpdateCountToSettle() {
35+
let renderingUpdateCount = 0;
36+
do {
37+
renderingUpdateCount = internals.renderingUpdateCount();
38+
// Wait slightly more than 2 frames at 60fps (~33.33ms) to ensure
39+
// any pending rendering updates have completed.
40+
await sleepFor(34);
41+
} while (internals.renderingUpdateCount() != renderingUpdateCount);
42+
43+
internals.startTrackingRenderingUpdates();
44+
}
45+
46+
window.addEventListener('load', async () => {
47+
if (!window.internals) {
48+
finishJSTest();
49+
return;
50+
}
51+
52+
description('Test that SVG animations on hidden elements do not trigger rendering updates.');
53+
54+
internals.setSpeculativeTilingDelayDisabledForTesting(true);
55+
56+
await waitForRenderingUpdateCountToSettle();
57+
58+
await sleepFor(250);
59+
60+
updateCount = internals.renderingUpdateCount();
61+
62+
shouldBeTrue('updateCount <= 5');
63+
64+
finishJSTest();
65+
}, false);
66+
</script>
67+
</body>
68+
69+
</html>

Source/WebCore/svg/SVGGraphicsElement.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,10 @@ void SVGGraphicsElement::svgAttributeChanged(const QualifiedName& attrName)
155155
return;
156156
}
157157

158-
if (CheckedPtr renderer = this->renderer())
158+
if (CheckedPtr renderer = this->renderer()) {
159159
renderer->setNeedsTransformUpdate();
160-
updateSVGRendererForElementChange();
160+
updateSVGRendererForElementChange();
161+
}
161162
return;
162163
}
163164

0 commit comments

Comments
 (0)