← All issues

[LBSE] Preserve paint order of non-composited children around composited SVG siblings

ea0009d

LBSE (Layer-Based SVG Engine) maps SVG elements to RenderLayers analogously to HTML, unlike the legacy single-backing-store SVG renderer. The compositor assembles a sibling list of GraphicsLayers for a container's children; composited children (will-change, 3D transforms, opacity promotions) become independent GraphicsLayers while non-composited children share a backing store. Because the compositor stacks layers in list order, a container with one shared non-composited backing plus several interleaved composited siblings cannot express arbitrary DOM paint order — the shared layer lands either entirely behind or entirely in front of all composited siblings.

LayoutTests/TestExpectations

-# webkit.org/b/308565 LBSE specific compositing tests
-svg/compositing/foreground-layer-composited-html-in-foreignobject-between-rects.html [ ImageOnlyFailure ]
-svg/compositing/foreground-layer-composited-svg-rect-and-foreignobject-interleaved.html [ ImageOnlyFailure ]
-svg/compositing/foreground-layer-mixed-svg-and-foreignobject-composited.html [ ImageOnlyFailure ]
-svg/compositing/foreground-layer-multiple-foreignobjects-composited.html [ ImageOnlyFailure ]

Source/WebCore/rendering/RenderLayerBackingSVGAdditions.cpp

+WebCore::RenderLayerBacking::updateSVGSegmentLayers
+WebCore::RenderLayerBacking::clearSVGSegmentLayers
+WebCore::RenderLayerBacking::svgSegmentLayerAfterCompositedChild
+WebCore::RenderLayerBacking::svgSegmentRangeForGraphicsLayer
+WebCore::RenderLayerBacking::computeSVGSegmentBounds
+WebCore::RenderLayerBacking::updateSVGSegmentLayerGeometry

This commit introduces paint-order segment overlay GraphicsLayers. The flat SVG child list is partitioned into [begin, end) half-open index ranges at each "anchor" (composited child) boundary; the leading run paints in the container's own backing store, and each subsequent run of non-composited children gets a named "(svg segment N)" GraphicsLayer inserted immediately after the preceding anchor in the compositor's child list. "Derived anchors" — elements that anchor only because a descendant is composited, so they paint inline — complicate boundary detection because an empty leading run before a derived anchor must still emit a segment. RenderSVGForeignObject is excluded from segmentation because it paints via HTML-style z-order lists rather than the SVG DOM-order paint path.

Flat child list: [r1, a1(composited), r2, r3, a2(composited), r4]

Before (broken):                     After (correct):
  container-primary → r1,r2,r3,r4      container-primary → slice [0,1) → r1
  a1 GraphicsLayer                     a1 GraphicsLayer   → a1's content
  a2 GraphicsLayer                     (svg segment 1)    → slice [2,4) → r2,r3
                                       a2 GraphicsLayer   → a2's content
                                       (svg segment 2)    → slice [4,6) → r4

This fixes a fundamental z-order correctness violation in the newer LBSE compositing pipeline that caused non-composited SVG siblings of animated/transformed elements to render in the wrong order. It also introduces a substantial new compositing subsystem with complex lifetime management, index arithmetic, and dynamic-update logic — a fresh attack surface.

🔒

New segment index arithmetic, derived-anchor boundary detection, and dynamic overlay layer lifecycle all present audit-worthy security investigation points.

Subscribe to read more