Update in-tree docs to point to the new book (#32743)

* Update in-tree docs to point to the new book

* Revive build setup section in README as quickstart guide

* Apply feedback about titles
This commit is contained in:
Delan Azabani 2024-07-09 23:42:00 +08:00 committed by GitHub
parent 72e6a1f007
commit 34d9be70f9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 63 additions and 1413 deletions

View file

@ -1,147 +1,6 @@
# Servo's style system overview
This document provides an overview of Servo's style system. For more extensive details,
refer to the [style doc comments][style-doc], or the [Styling
Overview][wiki-styling-overview] in the wiki, which includes a conversation between
Boris Zbarsky and Patrick Walton about how style sharing works.
Moved to the Servo book:
<a name="selector-impl"></a>
## Selector Implementation
To ensure compatibility with Stylo (a project integrating Servo's style system into Gecko),
selectors must be consistent.
The consistency is implemented in [selectors' SelectorImpl][selector-impl],
containing the logic related to parsing pseudo-elements and other pseudo-classes
apart from [tree-structural ones][tree-structural-pseudo-classes].
Servo extends the selector implementation trait in order to allow a few more
things to be shared between Stylo and Servo.
The main Servo implementation (the one that is used in regular builds) is
[SelectorImpl][servo-selector-impl].
<a name="dom-glue"></a>
## DOM glue
In order to keep DOM, layout and style in different modules, there are a few
traits involved.
Style's [`dom` traits][style-dom-traits] (`TDocument`, `TElement`, `TNode`,
`TRestyleDamage`) are the main "wall" between layout and style.
Layout's [`wrapper`][layout-wrapper] module makes sure that
layout traits have the required traits implemented.
<a name="stylist"></a>
## The Stylist
The [`stylist`][stylist] structure holds all the selectors and
device characteristics for a given document.
The stylesheets' CSS rules are converted into [`Rule`][selectors-rule]s.
They are then introduced in a [`SelectorMap`][selectors-selectormap] depending
on the pseudo-element (see [`PerPseudoElementSelectorMap`][per-pseudo-selectormap]),
stylesheet origin (see [`PerOriginSelectorMap`][per-origin-selectormap]), and
priority (see the `normal` and `important` fields in
[`PerOriginSelectorMap`][per-origin-selectormap]).
This structure is effectively created once per [pipeline][docs-pipeline], in the
corresponding LayoutThread.
<a name="properties"></a>
## The `properties` module
The [properties module][properties-module] is a mako template. Its complexity is derived
from the code that stores properties, [`cascade` function][properties-cascade-fn] and computation logic of the returned value which is exposed in the main function.
<a name="pseudo-elements"></a>
## Pseudo-Element resolution
Pseudo-elements are a tricky section of the style system. Not all
pseudo-elements are very common, and so some of them might want to skip the
cascade.
Servo has, as of right now, five [pseudo-elements][servo-pseudo-elements]:
* [`::before`][mdn-pseudo-before] and [`::after`][mdn-pseudo-after].
* [`::selection`][mdn-pseudo-selection]: This one is only partially
implemented, and only works for text inputs and textareas as of right now.
* `::-servo-details-summary`: This pseudo-element represents the `<summary>` of
a `<details>` element.
* `::-servo-details-content`: This pseudo-element represents the contents of
a `<details>` element.
Both `::-servo-details-*` pseudo-elements are private (i.e. they are only parsed
from User-Agent stylesheets).
Servo has three different ways of cascading a pseudo-element, which are defined
in [`PseudoElementCascadeType`][pseudo-cascade-type]:
<a name="pe-cascading-eager"></a>
### "Eager" cascading
This mode computes the computed values of a given node's pseudo-element over the
first pass of the style system.
This is used for all public pseudo-elements, and is, as of right now, **the only
way a public pseudo-element should be cascaded** (the explanation for this is
below).
<a name="pe-cascading-precomputed"></a>
### "Precomputed" cascading
Or, better said, no cascading at all. A pseudo-element marked as such is not
cascaded.
The only rules that apply to the styles of that pseudo-element are universal
rules (rules with a `*|*` selector), and they are applied directly over the
element's style if present.
`::-servo-details-content` is an example of this kind of pseudo-element, all the
rules in the UA stylesheet with the selector `*|*::-servo-details-content` (and
only those) are evaluated over the element's style (except the `display` value,
that is overwritten by layout).
This should be the **preferred type for private pseudo-elements** (although some
of them might need selectors, see below).
<a name="pe-cascading-lazy"></a>
### "Lazy" cascading
Lazy cascading allows to compute pseudo-element styles lazily, that is, just
when needed.
Currently (for Servo, not that much for stylo), **selectors supported for this
kind of pseudo-elements are only a subset of selectors that can be matched on
the layout tree, which does not hold all data from the DOM tree**.
This subset includes tags and attribute selectors, enough for making
`::-servo-details-summary` a lazy pseudo-element (that only needs to know
if it is in an `open` details element or not).
Since no other selectors would apply to it, **this is (at least for now) not an
acceptable type for public pseudo-elements, but should be considered for private
pseudo-elements**.
[style-doc]: https://doc.servo.org/style/index.html
[wiki-styling-overview]: https://github.com/servo/servo/wiki/Styling-overview
[selector-impl]: https://doc.servo.org/selectors/parser/trait.SelectorImpl.html
[selector-impl-ext]: https://doc.servo.org/style/selector_parser/trait.SelectorImplExt.html
[servo-selector-impl]: https://doc.servo.org/style/servo/selector_parser/struct.SelectorImpl.html
[tree-structural-pseudo-classes]: https://www.w3.org/TR/selectors4/#structural-pseudos
[style-dom-traits]: https://doc.servo.org/style/dom/index.html
[layout-wrapper]: https://doc.servo.org/layout/wrapper/index.html
[pseudo-cascade-type]: https://doc.servo.org/style/selector_parser/enum.PseudoElementCascadeType.html
[servo-pseudo-elements]: https://doc.servo.org/style/selector_parser/enum.PseudoElement.html
[mdn-pseudo-before]: https://developer.mozilla.org/en/docs/Web/CSS/::before
[mdn-pseudo-after]: https://developer.mozilla.org/en/docs/Web/CSS/::after
[mdn-pseudo-selection]: https://developer.mozilla.org/en/docs/Web/CSS/::selection
[stylist]: https://doc.servo.org/style/stylist/struct.Stylist.html
[selectors-selectormap]: https://doc.servo.org/style/selector_map/struct.SelectorMap.html
[selectors-rule]: https://doc.servo.org/style/stylist/struct.Rule.html
[per-pseudo-selectormap]: https://doc.servo.org/style/selector_parser/struct.PerPseudoElementMap.html
[per-origin-selectormap]: https://doc.servo.org/style/stylist/struct.PerOriginSelectorMap.html
[docs-pipeline]: https://github.com/servo/servo/blob/main/docs/glossary.md#pipeline
[properties-module]: https://doc.servo.org/style/properties/index.html
[properties-cascade-fn]: https://doc.servo.org/style/properties/fn.cascade.html
- Servos architecture
- [Style](https://book.servo.org/architecture/style.html)

View file

@ -1,78 +1,6 @@
# How WebXR works in Servo
## Terminology
Moved to the Servo book:
Servo's WebXR implementation involves three main components:
1. The script thread (runs all JS for a page)
2. The WebGL thread (maintains WebGL canvas data and invokes GL operations corresponding to [WebGL APIs](https://registry.khronos.org/webgl/specs/latest/1.0/))
3. The compositor (AKA the main thread)
Additionally, there are a number of WebXR-specific concepts:
* The [discovery object](https://doc.servo.org/webxr_api/trait.DiscoveryAPI.html) (ie. how Servo discovers if a device can provide a WebXR session)
* The [WebXR registry](https://doc.servo.org/webxr_api/struct.MainThreadRegistry.html) (the compositor's interface to WebXR)
* The [layer manager](https://doc.servo.org/webxr_api/layer/trait.LayerManagerAPI.html) (manages WebXR layers for a given session and frame operations on those layers)
* The [layer grand manager](https://doc.servo.org/webxr_api/layer/trait.LayerGrandManagerAPI.html) (manages all layer managers for WebXR sessions)
Finally, there are graphics-specific concepts that are important for the low-level details of rendering with WebXR:
* [surfman](https://github.com/servo/webxr/blob/main/webxr/glwindow/mod.rs#L448-L452) is a crate that abstracts away platform-specific details of OpenGL hardware-accelerated rendering
* [surface](https://doc.servo.org/surfman/platform/unix/default/surface/type.Surface.html) is a hardware buffer that are tied to a specific OpenGL context
* [surface texture](https://doc.servo.org/surfman/platform/unix/default/surface/type.SurfaceTexture.html) is an OpenGL texture that wraps a surface. Surface textures can be shared between OpenGL contexts.
* [surfman context](https://doc.servo.org/surfman/platform/unix/default/context/type.Context.html) represents a particular OpenGL context, and is backed by platform-specific implementations (such as EGL on Unix-based platforms)
* [ANGLE](https://github.com/servo/mozangle/) is an OpenGL implementation on top of Direct3D which is used in Servo to provide a consistent OpenGL backend on Windows-based platforms
## How Servo's compositor starts
The embedder is responsible for creating a window and [triggering the rendering context creation](https://github.com/servo/servo/blob/d7d0451424faf1bf9c705068bea1aa8cf582d6ad/ports/servoshell/headed_window.rs#L134) appropriately.
Servo creates the rendering context by [creating a surfman context](https://github.com/servo/servo/blob/d7d0451424faf1bf9c705068bea1aa8cf582d6ad/components/gfx/rendering_context.rs#L48-L58) which will
be [used by the compositor](https://github.com/servo/servo/blob/d7d0451424faf1bf9c705068bea1aa8cf582d6ad/components/servo/lib.rs#L467) for all [web content rendering operations](https://github.com/servo/servo/blob/d7d0451424faf1bf9c705068bea1aa8cf582d6ad/components/servo/lib.rs#L269-L281).
## How a session starts
When a webpage invokes `navigator.xr.requestSession(..)` through JS, this corresponds to the [XrSystem::RequestSession](https://github.com/servo/servo/blob/d7d0451424faf1bf9c705068bea1aa8cf582d6ad/components/script/dom/xrsystem.rs#L158) method in Servo.
This method [sends a message](https://github.com/servo/webxr/blob/614420b9830615376563fc6e1d98c52119f97123/webxr-api/registry.rs#L103-L108) to the [WebXR message handler](https://github.com/servo/webxr/blob/614420b9830615376563fc6e1d98c52119f97123/webxr-api/registry.rs#L193-L195)
that lives on the main thread, under the [control of the compositor](https://github.com/servo/servo/blob/d7d0451424faf1bf9c705068bea1aa8cf582d6ad/components/compositing/compositor.rs#L2049).
The WebXR message handler iterates over all known discovery objects and attempts to [request a session](https://github.com/servo/webxr/blob/614420b9830615376563fc6e1d98c52119f97123/webxr-api/registry.rs#L217-L231)
from each of them. The discovery objects encapsulate creating a session for each supported backend.
As of Feb 3, 2024, there are five WebXR backends:
* [magicleap](https://github.com/servo/webxr/tree/main/webxr/magicleap) - supports Magic Leap 1.0 devices
* [googlevr](https://github.com/servo/webxr/tree/main/webxr/googlevr) - supports Google VR
* [headless](https://github.com/servo/webxr/tree/main/webxr/headless) - supports a window-less, device-less device for automated tests
* [glwindow](https://github.com/servo/webxr/tree/main/webxr/glwindow) - supports a GL-based window for manual testing in desktop environments without real devices
* [openxr](https://github.com/servo/webxr/tree/main/webxr/openxr) - supports devices that implement the OpenXR standard
WebXR sessions need to [create a layer manager](https://github.com/servo/webxr/blob/main/webxr/glwindow/mod.rs#L448-L452)
at some point in order to be able to create and render to WebXR layers. This happens in several steps:
1. some initialization happens on the main thread
2. the main thread [sends a synchronous message](https://github.com/servo/servo/blob/d7d0451424faf1bf9c705068bea1aa8cf582d6ad/components/canvas/webgl_thread.rs#L3182-L3187) to the WebGL thread
3. the WebGL thread [receives the message](https://github.com/servo/servo/blob/d7d0451424faf1bf9c705068bea1aa8cf582d6ad/components/canvas/webgl_thread.rs#L392-L396)
4. some backend-specific, graphics-specific initialization happens on the WebGL thread, hidden behind the [layer manager factory](https://doc.servo.org/webxr_api/struct.LayerManagerFactory.html) abstraction
5. the new layer manager is [stored in the WebGL thread](https://github.com/servo/servo/blob/d7d0451424faf1bf9c705068bea1aa8cf582d6ad/components/canvas/webgl_thread.rs#L3058-L3061)
6. the main thread [receives a unique identifier](https://github.com/servo/servo/blob/d7d0451424faf1bf9c705068bea1aa8cf582d6ad/components/canvas/webgl_thread.rs#L3189-L3196) representing the new layer manager
This cross-thread dance is important because the device performing the rendering often has strict requirements for the compatibility of any
WebGL context that is used for rendering, and most GL state is only observable on the thread that created it.
## How an OpenXR session is created
The OpenXR discovery process starts at [OpenXrDiscovery::request_session](https://github.com/servo/webxr/blob/614420b9830615376563fc6e1d98c52119f97123/webxr/openxr/mod.rs#L309).
The discovery object only has access to whatever state was passed in its constructor, as well as a [SessionBuilder](https://doc.servo.org/webxr_api/struct.SessionBuilder.html)
object that contains values required to create a new session.
Creating an OpenXR session first [creates an OpenXR instance](https://github.com/servo/webxr/blob/614420b9830615376563fc6e1d98c52119f97123/webxr/openxr/mod.rs#L192),
which allows coniguring which extensions are in use. There are different extensions used to initialize OpenXR on different platforms; for Window
the [D3D extension](https://github.com/servo/webxr/blob/614420b9830615376563fc6e1d98c52119f97123/webxr/openxr/mod.rs#L213) can be used
since Servo relies on ANGLE for its OpenGL implementation.
Once an OpenXR instance exists, the session builder is used to create a new WebXR session that [runs in its own thread](https://github.com/servo/webxr/blob/614420b9830615376563fc6e1d98c52119f97123/webxr/openxr/mod.rs#L331).
All WebXR sessions can either [run in a thread](https://github.com/servo/webxr/blob/614420b9830615376563fc6e1d98c52119f97123/webxr-api/session.rs#L513-L538)
or have Servo [run them on the main thread](https://github.com/servo/webxr/blob/614420b9830615376563fc6e1d98c52119f97123/webxr-api/session.rs#L540-L552).
This choice has implications for how the graphics for the WebXR session can be set up, based on what GL state must be available for sharing.
OpenXR's new session thread [initializes an OpenXR device](https://github.com/servo/webxr/blob/614420b9830615376563fc6e1d98c52119f97123/webxr/openxr/mod.rs#L332-L337),
which is responsible for creating the actual OpenXR session. This session object is [created on the WebGL thread](https://github.com/servo/webxr/blob/614420b9830615376563fc6e1d98c52119f97123/webxr/openxr/mod.rs#L864-L878)
as part of creating the OpenXR layer manager, since it relies on [sharing the underlying GPU device](https://github.com/servo/webxr/blob/614420b9830615376563fc6e1d98c52119f97123/webxr/openxr/mod.rs#L443-L460) that the WebGL thread uses.
Once the session object has been created, the main thread can [obtain a copy](https://github.com/servo/webxr/blob/614420b9830615376563fc6e1d98c52119f97123/webxr/openxr/mod.rs#L878)
and resume initializing the [remaining properties](https://github.com/servo/webxr/blob/614420b9830615376563fc6e1d98c52119f97123/webxr/openxr/mod.rs#L882-L1026) of the new device.
- Servos architecture
- [WebXR](https://book.servo.org/architecture/webxr.html)