pH/sommelier/README.md
2019-09-20 18:57:28 -04:00

248 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Sommelier - Nested Wayland compositor with support for X11 forwarding
Sommelier is an implementation of a Wayland compositor that delegates
compositing to a 'host' compositor. Sommelier includes a set of features that
allows it to run inside a tight jail or virtual machine.
Sommelier can run as service or as a wrapper around the execution of a
program. As a service, it spawns new processes as needed to service clients.
The parent process is called the master sommelier.
## Sommeliers
### Master Sommelier
The master sommelier instance will create a wayland socket in XDG_RUNTIME_DIR
and accept connections from regular wayland clients. Each connection will be
serviced by spawning a child sommelier process.
### X11 Sommelier
An X11 sommelier instance provides X11 forwarding. Xwayland is used to
accomplish this. A single X11 sommelier instance is typically shared across
all X11 clients as they often expect that they can use a shared X server for
communication. If the X11 sommelier instance crashes in this setup, it takes
all running X11 programs down with it. Multiple X11 sommelier instances
can be used for improved isolation or when per-client configuration is
needed, but it will be at the cost of losing the ability for programs to use
the X server for communication between each other.
### Peer Sommelier
Each Linux program that support the Wayland protocol can have its own sommelier.
This provides better use of multiple cores when servicing clients, and it
prevents errors in one client from causing other clients to crash.
## Host Compositor Channel
Sommelier needs a channel to the host compositor in order to serve Wayland
clients inside a container. If the container environment provides a socket
that can be used to establish a connection to the host compositor, then
pointing sommelier to this socket using the `--display=DISPLAY` flag is
sufficient.
### VirtWL
The VirtWL device can be used to establish a new connection when no socket
is available (typically when running inside a VM). If a VirtWL device has been
specified (e.g. `--virtwl-device=/dev/wl0`) then sommelier will use this
mechanism by default to establish new channels between the host compositor and
sommelier instances. Data is forwarded between the VirtWL device and the core
Wayland dispatch mechanism using non-blocking I/O multiplexing.
## Shared Memory Drivers
Shared memory allocated inside a container cannot always be shared with the
host compositor. Sommelier provides a shared memory driver option as a
solution for this. What's the most appropriate option depends on the host
compositor and device drivers available for allocating buffers.
### Noop
The `noop` shared memory driver simply forwards buffers to the host without
any special processing. This requires that the client inside the container is
using memory that can be shared with the host compositor.
### VirtWL
The `virtwl` driver creates a set of intermediate virtwl buffers for each
surface, and copies minimal damaged areas from the clients standard shared
memory buffers into the virtwl buffers that can be shared with the host
compositor.
### VirtWL-DMABuf
The `virtwl-dmabuf` works the same way as the `virtwl` driver but allocates
buffers that can be shared with the host compositor using the linux_dmabuf
protocol. The benefits of using this driver over the basic `virtwl` driver
are:
* Larger set of supported formats (E.g NV12).
* Host compositor can avoid expensive texture uploads.
* HW overlays can be used for presentation if support by the host compositor.
### DMABuf
The `dmabuf` driver is similar to the `virtwl-dmabuf` driver. It creates a set
of intermediate buffers for each surface and copies minimal damaged areas from
the clients standard shared memory buffer into the DMABuf buffer. However,
the buffer is allocated using a DRM device and a prime FD is used to access
buffer memory inside the container. Intermediate buffers are shared with the
host compositor using the linux_dmabuf protocol.
## Damage Tracking
Shared memory drivers that use intermediate buffers require some form of
damage tracking in order to update intermediate buffers.
### Surface Buffer Queue
Each client surface in sommelier is associated with a buffer queue. Each
buffer in the buffer queue has a region (list of rectangles) that describes
the part of the buffer that is damaged compared to the last frame submitted
by the client. This provides high precision damage tracking across multiple
frames. Each new frame from the client adds damage to existing buffers. When
submitting a frame to the host compositor, the next available buffer is
dequeued and updated to not contain any damage. This is done by copying
contents from the current client buffer into the dequeued buffer.
The client's buffer is released as soon as this copy operation described above
is complete and the client can then reuse the shared memory buffer for another
frame.
Note: It is important to release the buffer immediately as clients dont
expect it to be held by the compositor for long when using shared memory.
### Back Pressure
Sommelier doesnt provide any back pressure for when the client is producing
contents faster than the host compositor can consume it. The size of the
buffer queue can as a result grow large. This is not a problem as Xwayland
and other clients handle back pressure themselves using Wayland frame
callbacks or similar mechanism.
## Data Drivers
Socket pairs created inside a container cannot always be shared with the
host compositor. Sommelier provides a data driver option as a solution
for this.
### Noop
The `noop` driver simply forwards socket pair FDs to the host without any
special processing. This requires that the client inside the container is
using socket pairs that can be shared with the host compositor.
### VirtWL
The `virtwl` driver creates a special pipe that can be shared with the host
compositor and forwards all data received over this pipe to the client FD.
Forwarding is done using non-blocking I/O multiplexing.
## Flags and Settings
Sommelier has two forms of configuration. Command line flags and environment
variables. Standard practice is to expose each option both as a command line
flag and as an environment variable. Command line flags will always override
the configuration provided by environment variables. This makes it easy to
run sommelier as a systemd service and allow the system-wide configuration
to be overridden using a local user provided systemd override file.
## Density and Scaling
A protocol aware proxy compositor between the client and the host compositor
makes it easier to support Linux programs that lack good HiDPI support.
It can also be used to adjust the scale of contents to support the dynamic
density changes that Chrome OS UI provide, and it gives the user an option
override any density decisions made by the host compositor. For example,
HiDPI aware programs can run at native display resolution, while some older
programs can use half of that resolution.
### Contents Scaling
Contents scaling can be applied to both native wayland clients and X11
clients. It can be controlled using the `--scale=SCALE` flag or
`SOMMELIER_SCALE=SCALE` variable. Where `SCALE` is a display density
multiplier. For example, if the default density is 200 DPI, then using
`--scale=0.5` will result in contents produced for 100 DPI.
### Scale Factor
An optimal scale factor is calculated for Wayland clients based on contents
scale setting and the current host compositor scaling. This allows Wayland
clients to produce contents at an optimal resolution for all combinations of
scaling used by sommelier and the host compositor.
### DPI
An exact value for DPI is calculated by sommelier. However, many Linux
programs expect DPI to be one out of a well known set of values. Sommelier
solves this by adjusting DPI using a set of buckets. For example, given the
default set of buckets (72, 96, 160, 240), Sommelier will use 96 as DPI when
the exact value is 112, or 160 when exact value is 188. The DPI buckets that
sommelier should use can be specified with `--dpi=[DPI[,DPI...]]`. Where,
`--dpi=””` will result in sommelier exposing the exact DPI value to clients.
### XCursor
Sommelier will set `XCURSOR_SIZE` environment variable automatically based on
the contents scale and preferred host compositor scale factor.
## Accelerators
If the host compositor support dynamic handling of keyboard events, then
keyboard shortcuts are forwarded to the Linux program by default. A small set
of shortcuts are expected to be reserved by the host compositor. A list of
reserved shortcuts on Chrome OS can be found
[here](https://chromium.googlesource.com/chromium/src/+/master/ash/accelerators/accelerator_table.h#22).
Theres unfortunately no reliable way to detect if a Linux program handled a
key event or not. This means that all non-reserved shortcuts that the user
want the host compositor to handle needs to be explicitly listed as an
accelerator. For example, on Chrome OS, the launcher can be brought up using
the "launcher" button during normal usage. The "launcher" button event is
forwarded to Linux programs by default so it wont work when a Linux program
has keyboard focus unless this shortcut is explicitly listed as an accelerator.
Sommelier provides the `--accelerator=ACCELERATORS` flag for this purpose.
`ACCELERATORS` is a comma separated list of accelerators that shouldnt be
forwarded to the Linux program but instead handled by the host compositor.
Each accelerator can contain a list of modifiers (e.g. `<Control><Alt>`) and
must be followed by an XKB keysym. The `xev` utility can be used to determine
what the XKB keysym is for a specific key. Given the launcher button example
above (which happens to have XKB keysym `Super_L` on the Chromebook Pixel),
`--accelerators=Super_L` needs to be passed to sommelier for the this button to
bring up the application launcher when Linux programs have keyboard focus.
Consistent with other flags, `SOMMELIER_ACCELERATORS` environment variable can
be used as an alternative to the command line flag.
## Examples
Start master sommelier and use wayland-1 as name of socket to listen on:
```
sommelier --master --socket=wayland-1
```
Start sommelier that runs weston-terminal with density scale multiplier 1.5:
```
sommelier --scale=1.5 weston-terminal
```
Start sommelier that runs inkscape with density scale multiplier 0.75 and 120
dots per inch (note that -X is specified as inkscape is an X11 client and
requires X11 forwarding):
```
sommelier -X --scale=0.75 --dpi=120 inkscape
```
Start sommelier that runs gedit with some accelerators reserved to the host
compositor instead of being sent to gedit:
```
sommelier --accelerators="<Alt>Bracketright,<Alt>Bracketleft" gedit
```