Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 6bd9478e8fd2f401e6539f1263e9e32c1f9f2880
      
https://github.com/WebKit/WebKit/commit/6bd9478e8fd2f401e6539f1263e9e32c1f9f2880
  Author: Nikolas Zimmermann <[email protected]>
  Date:   2026-07-10 (Fri, 10 Jul 2026)

  Changed paths:
    M 
LayoutTests/platform/mac-tahoe-wk2-lbse-text/svg/repaint/image-repainting-after-modifying-transform-repaint-rects-expected.txt
    A 
LayoutTests/platform/mac-tahoe-wk2-lbse-text/svg/repaint/nested-transform-change-static-parent-repaint-expected.txt
    M 
LayoutTests/platform/mac-tahoe-wk2-lbse-text/svg/repaint/shape-repainting-after-modifying-transform-repaint-rects-expected.txt
    A 
LayoutTests/svg/repaint/nested-transform-change-static-parent-repaint-expected.txt
    A LayoutTests/svg/repaint/nested-transform-change-static-parent-repaint.html
    M Source/WebCore/page/LocalFrameViewLayoutContext.cpp
    M Source/WebCore/rendering/ReferencedSVGResources.cpp
    M Source/WebCore/rendering/RenderLayerModelObject.cpp
    M Source/WebCore/rendering/svg/RenderSVGImage.cpp

  Log Message:
  -----------
  [LBSE] Coalesce the SVG transform flush into one minimal repaint per container
https://bugs.webkit.org/show_bug.cgi?id=318850

Reviewed by Rob Buis.

LocalFrameViewLayoutContext::flushPendingSVGTransformAttributeUpdatesIfNeeded
runs once per rendering update and processes every SVG renderer whose transform
changed since the last update, whether from a scripted change or an
animation. Its repaint pass was the dominant per-frame cost at
MotionMark/Suits. This rework makes that pass cheaper and issues
fewer, smaller invalidations, closing the gap to the legacy SVG engine.

Repaint rects are now mapped with RepaintOutlineBounds::No. For SVG the outline
bounds equal the visual overflow, so requesting them mapped a redundant second
rect up the container chain every frame, work the legacy engine already avoided.

Rather than walking each moved renderer to its repaint container, the flush now
computes each non-layered child's rect in its parent's coordinate space by
applying the SVG transform and the location offset, unions the children per
parent, and maps each parent's single union to the repaint container once. This
replaces N ancestor-chain walks with N cheap transforms plus one walk per 
parent.
A child whose parent also moved this frame, a child whose parent clips overflow,
and any renderer that is not a plain RenderSVGModelObject fall back to the exact
per-shape mapping.

The moved rects are then accumulated into one union per repaint container and
flushed with a single repaintUsingContainer() per container instead of one per
shape, collapsing N backing-store invalidations into one while keeping the
repainted region minimal.

Because this path never lays out, it also has to refresh the caches that layout
would. updateTransformAndRepaintForSVGAfterAttributeChange, which applies the
queued change to a single renderer, now also invalidates the bounding boxes and
cached visual overflow rect of that renderer's ancestors up to the SVG root, so
getBBox() and paint or hit-test culling never read a stale rect before the next
layout. It skips that walk when the transform did not actually change or when a
relayout is already scheduled.

Finally, a marker or clip-path change can resize the element that references it.
When that referencing element has no layer it gets no post-layout position
update, so it now repaints its old bounds before invalidating its cached visual
overflow, letting a shrunk element erase the area it used to cover. Paint
servers, whose bounds do not change, are excluded. RenderSVGImage gains the same
eager post-layout visual-overflow refresh RenderSVGShape already had, so the old
bounds are available when that repaint runs.

A test, svg/repaint/nested-transform-change-static-parent-repaint.html, covers a
shape whose ancestor transform changes in the same flush: the shape's previous
position must still be repainted. The two existing
*-repainting-after-modifying-transform-repaint-rects tests now record one union
rect instead of several separate rects, with identical rendering, and their LBSE
baselines are updated here.

* 
LayoutTests/platform/mac-tahoe-wk2-lbse-text/svg/repaint/image-repainting-after-modifying-transform-repaint-rects-expected.txt:
* 
LayoutTests/platform/mac-tahoe-wk2-lbse-text/svg/repaint/nested-transform-change-static-parent-repaint-expected.txt:
 Added.
* 
LayoutTests/platform/mac-tahoe-wk2-lbse-text/svg/repaint/shape-repainting-after-modifying-transform-repaint-rects-expected.txt:
* 
LayoutTests/svg/repaint/nested-transform-change-static-parent-repaint-expected.txt:
 Added.
* LayoutTests/svg/repaint/nested-transform-change-static-parent-repaint.html: 
Added.
* Source/WebCore/page/LocalFrameViewLayoutContext.cpp:
(WebCore::LocalFrameViewLayoutContext::flushPendingSVGTransformAttributeUpdatesIfNeeded):
* Source/WebCore/rendering/ReferencedSVGResources.cpp:
(WebCore::CSSSVGResourceElementClient::resourceChanged):
* Source/WebCore/rendering/RenderLayerModelObject.cpp:
(WebCore::RenderLayerModelObject::updateTransformAndRepaintForSVGAfterAttributeChange):
* Source/WebCore/rendering/svg/RenderSVGImage.cpp:
(WebCore::RenderSVGImage::layout):

Canonical link: https://commits.webkit.org/316880@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to