Introducing the layer based SVG engine

  1. SVG PoC patch
↑ Table Of Contents

The bug report #90738 Harmonize HTML/SVG rendering - dating back to 2012 - contains the latest revision of a single patch that replaces the legacy SVG engine with the layer based SVG engine.

That patch size is almost 18 MB, mostly because of changes in the Render Tree dumps due to the introduction of layers in the SVG Render Tree. The intention of uploading a single large patch to WebKit Bugzilla is to run the Early Warning System (EWS), which tests the patch under various conditions and platforms. Obviously a huge patch like this is not intended for landing, nor to get a precise review, it’s just too large.

To ease the following discussions I’m sharing the full Git repository that was used to build the patch on Bugzilla. It contains a snapshot of WebKit Git main branch (at the time of writing: from mid-October 2021) plus 7 patches on top that implement the layer based SVG engine. It is the same branch that I’m using for regular development. Compared to the patch on Bugzilla the changes in that repository are even larger, because it additionally contains an updated pixel test baseline for the LayoutTests/svg subdirectory, that I’ve omitted for the Bugzilla patch as pixel tests are not running on the bots.

As some of you might remember, WebKit used to run pixel tests on the bots, but it was a nightmare to maintain. However hundreds of SVG tests still rely on pixel testing and haven’t been converted to reftests so far (Volunteers welcome!). Regressions in those kind of tests can only be found by comparing pixel results at present. Therefore a pixel test baseline was generated on macOS Big Sur before applying the layer based SVG engine patch. A lot of work went into getting all (well most, there are a few known regressions) layout tests pixel perfect with respect to the legacy SVG engine. This was only done for the LayoutTests/svg subdirectory and selectively outside, e.g. in compositing/.

Let’s have a look at the individual patches in the repository:

(1) 138d8200 - Add macOS Big Sur pixel test baseline for svg/ subdirectory for testing purposes
      This commits adds a pixel test baseline generated using macOS Big Sur on an Apple M1 laptop.
(2) 0562fcba - Integrate new layer based SVG engine
      This commit contains all code changes in Source/.
(3) ed647f0e - Add new layout tests
      This commit contains only new layout tests.
(4) 40d316c7 - Update existing layout tests (fix bugs, etc.)
      This commit resolves a few bugs in existing layout tests (e.g. <foreignObject> misuse).
(5) 2c44a6cc - Update text result baseline
      This commit contains updates of all “-expected.txt” files, due to the changed Render Tree dumps.
(6) 7e6a16d6 - Update macOS Big Sur pixel test baseline for svg/ subdirectory
      This commit updates some pixel test results, that have changed with respect to patch 1.
(7) 8fc0a553 - Update test expectations
      This commits updates the TestExpectations file to mark known regressions.

The patch on Bugzilla was created by squashing patches (2), (5) and (7) into a single commit.
Let’s analyze the code changes in patch (2).

7.1. Code changes ↑ Table Of Contents

The bulk of the changes are located in Source/WebCore/rendering and Source/WebCore/svg, and a few changes outside. Here’s a full list of all changed files:

commit 0562fcba9be2ec300dc8654a68e4331f235a687b
Author: Nikolas Zimmermann <nzimmermann@igalia.com>
Date:   Sat Sep 11 01:50:25 2021 -0700

    Integrate new layer based SVG engine

 Source/WTF/wtf/Assertions.cpp                                         |  36 +++---
 Source/WebCore/Sources.txt                                            |   7 +-
 Source/WebCore/WebCore.xcodeproj/project.pbxproj                      |  30 ++++-
 Source/WebCore/accessibility/AccessibilityRenderObject.cpp            |   2 +-
 Source/WebCore/css/CSSComputedStyleDeclaration.cpp                    |   2 +-
 Source/WebCore/css/CSSCursorImageValue.cpp                            |   2 +-
 Source/WebCore/css/CSSToStyleMap.cpp                                  |   2 +-
 Source/WebCore/dom/Element.cpp                                        |  23 ++--
 Source/WebCore/editing/TextIterator.cpp                               |   3 +-
 Source/WebCore/page/EventHandler.cpp                                  |   7 +-
 Source/WebCore/page/PerformanceNavigationTiming.cpp                   |   2 -
 Source/WebCore/page/mac/PageMac.mm                                    |   1 +
 Source/WebCore/platform/graphics/FloatLine.h                          |  10 ++
 Source/WebCore/platform/graphics/GraphicsLayer.cpp                    |   1 +
 Source/WebCore/platform/graphics/GraphicsLayer.h                      |   4 +
 Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp               |   6 +-
 Source/WebCore/platform/graphics/coretext/FontCoreText.cpp            |  45 +++++--
 Source/WebCore/platform/graphics/filters/Filter.h                     |   1 +
 Source/WebCore/platform/graphics/filters/FilterEffect.cpp             |   2 +-
 Source/WebCore/platform/graphics/transforms/TransformState.cpp        |  27 +++-
 Source/WebCore/platform/graphics/transforms/TransformState.h          |   9 +-
 Source/WebCore/rendering/CSSFilter.cpp                                |  86 ++++++++++---
 Source/WebCore/rendering/CSSFilter.h                                  |  26 ++--
 Source/WebCore/rendering/InlineBoxPainter.cpp                         |  25 ++++
 Source/WebCore/rendering/InlineBoxPainter.h                           |   1 +
 Source/WebCore/rendering/LegacyInlineFlowBox.cpp                      |   4 +-
 Source/WebCore/rendering/PaintPhase.h                                 |   2 +-
 Source/WebCore/rendering/RenderBlock.cpp                              |   7 +-
 Source/WebCore/rendering/RenderBox.cpp                                |  63 +++++++--
 Source/WebCore/rendering/RenderBox.h                                  |   5 +-
 Source/WebCore/rendering/RenderElement.cpp                            |  22 ----
 Source/WebCore/rendering/RenderElement.h                              |   5 +-
 Source/WebCore/rendering/RenderGeometryMap.cpp                        |   2 +-
 Source/WebCore/rendering/RenderLayer.cpp                              | 943 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
 Source/WebCore/rendering/RenderLayer.h                                |  64 +++++++--
 Source/WebCore/rendering/RenderLayerBacking.cpp                       | 212 +++++++++++++++++++-----------
 Source/WebCore/rendering/RenderLayerBacking.h                         |   5 +-
 Source/WebCore/rendering/RenderLayerCompositor.cpp                    |   4 +-
 Source/WebCore/rendering/RenderLayerFilters.cpp                       | 179 ++++++++++++++++++++++----
 Source/WebCore/rendering/RenderLayerFilters.h                         |  10 +-
 Source/WebCore/rendering/RenderLayerHTML.cpp                          |  90 +++++++++++++
 Source/WebCore/rendering/RenderLayerHTML.h                            |  49 +++++++
 Source/WebCore/rendering/RenderLayerModelObject.cpp                   |  24 +++-
 Source/WebCore/rendering/RenderLayerModelObject.h                     |   4 +
 Source/WebCore/rendering/RenderLayerSVG.cpp                           | 108 ++++++++++++++++
 Source/WebCore/rendering/RenderLayerSVG.h                             |  49 +++++++
 Source/WebCore/rendering/RenderObject.cpp                             | 199 +++++++++++++++++++++-------
 Source/WebCore/rendering/RenderObject.h                               |  49 +++----
 Source/WebCore/rendering/RenderReplaced.cpp                           |  14 +-
 Source/WebCore/rendering/RenderTreeAsText.cpp                         |   2 +-
 Source/WebCore/rendering/RenderView.cpp                               |  72 ++++++++++-
 Source/WebCore/rendering/RenderView.h                                 |   1 +
 Source/WebCore/rendering/style/RenderStyle.cpp                        |  25 +++-
 Source/WebCore/rendering/style/RenderStyle.h                          |   2 +
 Source/WebCore/rendering/svg/RenderSVGBlock.cpp                       |  75 ++++-------
 Source/WebCore/rendering/svg/RenderSVGBlock.h                         |  27 ++--
 Source/WebCore/rendering/svg/RenderSVGContainer.cpp                   | 185 ++++++++++++++------------
 Source/WebCore/rendering/svg/RenderSVGContainer.h                     |  43 +++----
 Source/WebCore/rendering/svg/RenderSVGEllipse.cpp                     |   2 +-
 Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp               | 167 ++++++++++++------------
 Source/WebCore/rendering/svg/RenderSVGForeignObject.h                 |  26 ++--
 Source/WebCore/rendering/svg/RenderSVGGradientStop.h                  |   9 +-
 Source/WebCore/rendering/svg/RenderSVGHiddenContainer.cpp             |  45 ++++++-
 Source/WebCore/rendering/svg/RenderSVGHiddenContainer.h               |  10 +-
 Source/WebCore/rendering/svg/RenderSVGImage.cpp                       | 367 ++++++++++++++++++++++++++++++++++++++--------------
 Source/WebCore/rendering/svg/RenderSVGImage.h                         |  39 ++----
 Source/WebCore/rendering/svg/RenderSVGInline.cpp                      |  37 +-----
 Source/WebCore/rendering/svg/RenderSVGInline.h                        |   9 +-
 Source/WebCore/rendering/svg/RenderSVGInlineText.cpp                  |   6 +-
 Source/WebCore/rendering/svg/RenderSVGInlineText.h                    |   2 +-
 Source/WebCore/rendering/svg/RenderSVGModelObject.cpp                 | 220 ++++++++++++++++++++++---------
 Source/WebCore/rendering/svg/RenderSVGModelObject.h                   |  62 +++++++--
 Source/WebCore/rendering/svg/RenderSVGPath.cpp                        |   2 +-
 Source/WebCore/rendering/svg/RenderSVGRect.cpp                        |   2 +-
 Source/WebCore/rendering/svg/RenderSVGResource.cpp                    |   6 +-
 Source/WebCore/rendering/svg/RenderSVGResource.h                      |   5 +-
 Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp             | 306 +++++++++++++++++--------------------------
 Source/WebCore/rendering/svg/RenderSVGResourceClipper.h               |  45 +------
 Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp           |   7 +-
 Source/WebCore/rendering/svg/RenderSVGResourceContainer.h             |   4 +-
 Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp              | 292 ++---------------------------------------
 Source/WebCore/rendering/svg/RenderSVGResourceFilter.h                |  30 -----
 Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp            |  22 ++--
 Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.cpp      |   4 +-
 Source/WebCore/rendering/svg/RenderSVGResourceMarker.cpp              | 114 ++++++++--------
 Source/WebCore/rendering/svg/RenderSVGResourceMarker.h                |  27 ++--
 Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp              | 158 ++++++++++-------------
 Source/WebCore/rendering/svg/RenderSVGResourceMasker.h                |  20 ++-
 Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp             |  57 ++++----
 Source/WebCore/rendering/svg/RenderSVGResourcePattern.h               |   9 +-
 Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.cpp      |   8 +-
 Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.cpp          |  18 ++-
 Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.h            |   1 +
 Source/WebCore/rendering/svg/RenderSVGRoot.cpp                        | 513 ++++++++++++++++++++++++++++++++++++++++++++++++------------------------
 Source/WebCore/rendering/svg/RenderSVGRoot.h                          |  62 +++++----
 Source/WebCore/rendering/svg/RenderSVGShape.cpp                       | 194 +++++++++++++++++-----------
 Source/WebCore/rendering/svg/RenderSVGShape.h                         |  33 ++---
 Source/WebCore/rendering/svg/RenderSVGText.cpp                        | 164 ++++++++++++++---------
 Source/WebCore/rendering/svg/RenderSVGText.h                          |  34 ++---
 Source/WebCore/rendering/svg/RenderSVGTextPath.cpp                    |  12 +-
 Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp      |  99 ++++++++++----
 Source/WebCore/rendering/svg/RenderSVGTransformableContainer.h        |  23 ++--
 Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp           |  92 ++++++++-----
 Source/WebCore/rendering/svg/RenderSVGViewportContainer.h             |  34 +++--
 Source/WebCore/rendering/svg/SVGBoundingBoxComputation.cpp            | 267 ++++++++++++++++++++++++++++++++++++++
 Source/WebCore/rendering/svg/SVGBoundingBoxComputation.h              |  88 +++++++++++++
 Source/WebCore/rendering/svg/SVGContainerLayout.cpp                   | 313 ++++++++++++++++++++++++++++++++++++++++++++
 Source/WebCore/rendering/svg/SVGContainerLayout.h                     |  55 ++++++++
 Source/WebCore/rendering/svg/SVGInlineFlowBox.cpp                     |  25 +++-
 Source/WebCore/rendering/svg/SVGInlineTextBox.cpp                     |  48 +++++--
 Source/WebCore/rendering/svg/SVGLayoutLogger.cpp                      | 190 +++++++++++++++++++++++++++
 Source/WebCore/rendering/svg/SVGLayoutLogger.h                        |  68 ++++++++++
 Source/WebCore/rendering/svg/SVGLogger.cpp                            | 182 ++++++++++++++++++++++++++
 Source/WebCore/rendering/svg/SVGLogger.h                              | 219 +++++++++++++++++++++++++++++++
 Source/WebCore/rendering/svg/SVGPathData.cpp                          | 249 ++++++++++++++++++++++++++---------
 Source/WebCore/rendering/svg/SVGPathData.h                            |   5 +-
 Source/WebCore/rendering/svg/SVGRenderSupport.cpp                     | 575 +++++++++++++++++++++++++++++++++++++++------------------------------------------
 Source/WebCore/rendering/svg/SVGRenderSupport.h                       |  53 ++++----
 Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp                  |  23 ++--
 Source/WebCore/rendering/svg/SVGRenderingContext.cpp                  | 254 +++++-------------------------------
 Source/WebCore/rendering/svg/SVGRenderingContext.h                    |  53 +-------
 Source/WebCore/rendering/svg/SVGResources.cpp                         |  13 +-
 Source/WebCore/rendering/svg/SVGResources.h                           |   1 -
 Source/WebCore/rendering/svg/SVGRootInlineBox.cpp                     |  32 +++--
 Source/WebCore/rendering/svg/SVGRootInlineBox.h                       |   2 +-
 Source/WebCore/rendering/svg/SVGTextChunk.cpp                         |   2 +-
 Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp       |   6 +-
 Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp                  |  14 +-
 Source/WebCore/rendering/svg/SVGTextLayoutEngineBaseline.cpp          |   3 +-
 Source/WebCore/rendering/svg/SVGTextLayoutEngineSpacing.cpp           |   6 +-
 Source/WebCore/rendering/updating/RenderTreeBuilderFirstLetter.cpp    |   1 +
 Source/WebCore/style/StyleAdjuster.cpp                                |  47 ++++++-
 Source/WebCore/style/StyleBuilderConverter.h                          |   9 +-
 Source/WebCore/svg/SVGAnimateMotionElement.cpp                        |  11 +-
 Source/WebCore/svg/SVGElement.cpp                                     |   8 +-
 Source/WebCore/svg/SVGElement.h                                       |   7 +-
 Source/WebCore/svg/SVGFEConvolveMatrixElement.cpp                     |   4 +-
 Source/WebCore/svg/SVGFEImageElement.cpp                              |   3 +-
 Source/WebCore/svg/SVGFontFaceElement.cpp                             |   4 +-
 Source/WebCore/svg/SVGGraphicsElement.cpp                             |  46 +------
 Source/WebCore/svg/SVGGraphicsElement.h                               |   4 +-
 Source/WebCore/svg/SVGImageElement.cpp                                |  37 +++---
 Source/WebCore/svg/SVGImageElement.h                                  |   3 +-
 Source/WebCore/svg/SVGLength.h                                        |   9 +-
 Source/WebCore/svg/SVGLengthContext.cpp                               | 108 +++++++++-------
 Source/WebCore/svg/SVGLengthContext.h                                 |  40 ++++--
 Source/WebCore/svg/SVGLengthValue.cpp                                 |  15 ++-
 Source/WebCore/svg/SVGLineElement.cpp                                 |   1 +
 Source/WebCore/svg/SVGLocatable.cpp                                   |  45 +++++--
 Source/WebCore/svg/SVGLocatable.h                                     |   2 -
 Source/WebCore/svg/SVGPatternElement.cpp                              |   5 -
 Source/WebCore/svg/SVGPatternElement.h                                |   2 -
 Source/WebCore/svg/SVGPreserveAspectRatioValue.cpp                    |  95 ++++++++++++++
 Source/WebCore/svg/SVGPreserveAspectRatioValue.h                      |   2 +
 Source/WebCore/svg/SVGSVGElement.cpp                                  |  80 ++----------
 Source/WebCore/svg/SVGSVGElement.h                                    |   2 -
 Source/WebCore/svg/SVGTextElement.cpp                                 |  24 ----
 Source/WebCore/svg/SVGTextElement.h                                   |   2 -
 Source/WebCore/svg/SVGTransform.h                                     |   2 +-
 Source/WebCore/svg/SVGTransformable.h                                 |   3 -
 Source/WebCore/svg/SVGURIReference.cpp                                |  19 +--
 Source/WebCore/svg/SVGURIReference.h                                  |   2 +-
 Source/WebCore/svg/SVGUseElement.cpp                                  |  20 ---
 Source/WebCore/svg/SVGUseElement.h                                    |   1 -
 Source/WebCore/svg/SVGViewElement.cpp                                 |   1 +
 Source/WebCore/svg/graphics/SVGImage.cpp                              |   5 +-
 Source/WebCore/svg/graphics/filters/SVGFEImage.cpp                    |  33 ++---
 Source/WebCore/svg/graphics/filters/SVGFilter.cpp                     |  50 -------
 Source/WebCore/svg/graphics/filters/SVGFilter.h                       |  60 ---------
 Source/WebCore/svg/properties/SVGAnimationAdditiveListFunctionImpl.h  |   4 +-
 Source/WebCore/svg/properties/SVGAnimationAdditiveValueFunctionImpl.h |   6 +-
 171 files changed, 6439 insertions(+), 3432 deletions(-)

I cannot discuss each individual change, but we can at least highlight the key changes:

  • Introduce two new RenderLayer derived classes: RenderLayerHTML and RenderLayerSVG that implement HTML/SVG specific functions to query geometry information from RenderBox / RenderSVGModelObject, respectively.

  • Teach RenderLayer / RenderLayerBacking about RenderSVGModelObject, as described earlier in this document.

  • Introduce SVGBoundingBoxComputation, which implements the SVG2 object bounding box rules. Switch all SVG renderers to utilize SVGBoundingBoxComputation.

    SVG2 also exposes the new computation possibilities to the Web using the SVGBoundingBoxOptions data structure, that can be passed as optional parameter to SVGGraphicsElement::getBBox(). This part has not been implemented so far, currently SVGBoundingBoxComputation is only used internally.

  • Introduce SVGContainerLayout, which implements the two-pass procedure to layout SVG containers, following the recipe presented earlier in this document. Switch all RenderSVGContainer derived renderers to utilize SVGContainerLayout to layout its descendants.

  • Introduce SVGLayoutLogger, a new helper class to trace the SVG layout / paint code across layers. It offers an alternative view of the SVG render tree, visualizing the Render Tree in ASCII art, with additional information related to SVG/CSS geometry information from the renderers and layers.

    It can be triggered on macOS using notifyutil -p com.apple.WebKit.showSVGRenderTree.

  • Make Filter class usable for SVG filters by adding absoluteTransform support, that previously lived in SVGFilter. Remove the SVGFilter class, since SVG filters now use RenderLayerFilters / CSSFilter.

  • Teach CSSFilter about SVG features: effectBoundingBoxMode, absoluteTransform support. This allows RenderLayerFilters to fully support SVG filters applied to both SVG and HTML content.

  • Extend TransformState to allow to compute the matrices needed by SVGLocatable::getCTM() and SVGLocatable::getScreenCTM(). Computing CTM / Screen CTM now boils down to calling mapLocalToContainer(), which reduces the need for SVG only code to compute transform matrices.

  • Remove code from RenderElement, that explicitly disables layer creation for the SVG subtree (layerCreationAllowedForSubtree() / parts of didAttachChild()).

  • Remove hacks in RenderSVGForeignObject that simulated the existence of a stacking context, by painting all phases of each <foreignObject> atomically. RenderSVGForeignObject now establishes a stacking context and serves as containing block for its descendants, it’s now treated as absolutely positioned element within the CSS layout code, as demanded by the specification.

  • Rewrite RenderSVGImage, based on the RenderImage design, aligning the two renderers as close as possible. More code sharing is possible in future.

  • Introduce RenderLayerModelObject::applyTransform() and switch RenderLayer to use it, instead of directly querying the RenderStyle for the transform (RenderStyle::applyTransform()). This allows SVG renderers, such as RenderSVGViewportContainer / RenderSVGTransformableContainer to hook in and apply additional SVG specific transformations on top of the CSS transform.

  • Remove SVGs own masking code from RenderSVGResourceMasker, turning RenderSVGResourceMasker::applyResource() into a no-op. SVG masking is now handled via RenderLayer.

  • Rewrite SVG (mask based) clipping code in RenderSVGResourceClipper. Switch from rendering masks into a ImageBuffer and utilizing SVGRenderingContext::clipToImageBuffer() to avoid any temporary buffers and instead use CSS composite operations (DestinationIn) combined with transparency layers. Just like for masks, RenderSVGResourceClipper::applyResource() is now a no-op, since RenderLayer is responsible to handle (SVG) clipping.

  • Remove SVG filter code from RenderSVGResourceFilter. RenderLayerFilters now handles SVG filter code, besides CSS.

  • Introduce an TinyLRUCache based cache for SVGPathData, to avoid excessive Path object creations.

  • Remove the majority of the code from SVGRenderingContext / SVGRenderSupport.

  • Remove code handling CSS transforms from SVGGraphicsElement::animatedLocalTransform(). SVGGraphicsElement no longer needs to handle CSS transform related code, the integration happens via the new applyTransform() method in RenderLayerModelObject instead.

  • Teach StyleAdjuster about SVG2 rules when to establish a stacking context within SVG documents.

This covers the most important changes, please check the patch on your own to see all details.

7.2. Performance ↑ Table Of Contents

Performance measurements were carried out on both desktop grade machines (GTK / WPE / macOS ports) and embedded devices (WPE port).

The goal is to preserve the rendering performance in all cases, that do not have a benefit from layer based painting. If an animation is driven by e.g. requestAnimationFrame() and the JavaScript code modifies SVG DOM in such a way that relayout is required (e.g. by modifying the ‘width’ / ‘height’ attribute values of a <rect>) managing the layer data structures is an additional overhead with respect to the legacy SVG engine. Therefore special attention was paid to improve the overall rendering performance to compensate for the additional overhead due to the management of layers.

The SVG Suits test suite, part of the MotionMark 1.1 benchmark was used as primary benchmark to assess the rendering performance or the cases, where layer based rendering is an overhead, not an improvement. With this patch (tested a few months ago though) the results between the both SVG engines were consistent: the layer based SVG engine is performance neutral on SVG Suits, although individual benchmarks are better than before, some worse. This is not the end of the story, there’s still a lot of room for optimization.

Now let’s discuss the test cases that actually benefit from layers. In these cases the results are stunning compared to the legacy SVG engine: fluent animations at 60 FPS even on low-powered embedded devices, that were notoriously slow before! An earlier blog post, CSS 3D transformations & SVG shows the performance of CSS Animations on an embedded device as well as 3D transformations applied to SVG elements utilizing WPE WebKit.

The most recent update was given during the WebKit contributor meeting a few weeks ago. In case you missed the presentation, please check out the video, recently uploaded to YouTube:

The presentation was well received by the community and the opportunity was used to discuss and develop an upstreaming strategy that I’ll present in the following.

Note that I intentionally leave out raw performance metrics here, as the SVG PoC patch won’t be upstreamed as-is anyhow and I don’t want to nail down numbers here, that are likely to change soon (for the better!).

7.3. Upstreaming strategy ↑ Table Of Contents

During the WebKit contributors meeting a possible upstreaming strategy was discussed, that I’ll summarize in the following:

Introduce a runtime enabled feature flag, to switch to the layer based SVG engine. The current SVG engine will be referred to as legacy SVG engine in the following.

Upstream the layer based SVG engine in small, atomic chunks, while keeping the legacy SVG engine* intact and on by default. To reach *small*, *atomic* chunks the following strategy was proposed:

  • If a file content has changed significantly between the two branches (WebKit with(out) SVG patch), rename the affected files and data structures. RenderSVGRoot, for example, has changed a lot in the layer based SVG engine. Therefore the current version shall be renamed to LegacyRenderSVGRoot and RenderSVGRoot.cpp should be renamed to LegacyRenderSVGRoot.cpp.

    Afterwards a new RenderSVGRoot.cpp file can be created as stub, that can be filled with content in follow-up patches.

  • If a file only changed slightly, keep the file as-is, and place the code supporting the layer based SVG engine behind conditionals, depending on the new runtime enabled feature flag.

This approach allows to build the layer based SVG engine into WebCore in an incremental way. Once enough is upstreamed that first tests pass, one can selectively switch individual tests to run with the layer based SVG engine, gradually migrating to it.

Finally at some point in future, if upstreaming completed we can get rid of the legacy SVG engine.

7.4. LFC integration ↑ Table Of Contents

Layout Formatting Context (LFC) is the umbrella name of a project that intends to rewrite WebKits layout and paint code at the same time, to de-convolute it and allow for advanced features such as parallel layout. Similar efforts from other vendors are Servo in Firefox and LayoutNG in Chrome.

The ultimate goal is to replace the Render Tree and Layout Tree, by two new data structures that avoid mistakes made in the past, and allow for parallelization of operations such as layout. These are named LFC Layout Tree and LFC Display Tree.

Currently, while integration of LFC is ongoing, the LFC Layout Tree is built from the Render Tree, utilizing LayoutTreeBuilder. At some point the LFC Layout Tree will become self-hosting, not requiring the Render Tree anymore, but that’s likely a few years away in the future.

The LFC Display Tree is partly described in the WebKit repository.

The display tree is intended to be a fully-resolved, isolated tree that is suitable for painting and hit-testing.

Fully-resolved means that all style values have been resolved to the values use for painting. For example, colors in the display tree are those which result from the application of visited link rules, and from the application of -apple-color-filter.

Isolated means that a display tree is a stand-alone data structure that can be painted without reference to data structures share with layout. For example, the display tree does not use RenderStyle once built, but constructs its own display styles at tree-building time.

Furthermore it states:

All the geometry in the display tree is already in painting coordinates: pixel snapping happens at tree building time. In general the tree has been designed to push as much of the complexity to tree-building time as possible, so that painting is fast.

The SVG integration in LFC should be straight-forward and even easier with the layer-based SVG engine, as the renderers and their structure is much more similar to the standard CSS renderers, like RenderBox / RenderBlock.

In my view, getting the layer based SVG engine into WebKit upstream can be done first, before considering the LFC integration.

Navigation: Previous     Next
comments powered by Disqus