mirror of
https://gitlab.freedesktop.org/emersion/libliftoff.git
synced 2024-12-26 21:59:18 +01:00
6321e7c5aa
Right now, compositors are expected to query liftoff_layer_get_plane_id to decide whether a layer needs to be composited. However there are cases where a layer has no plane, but still doesn't need composition (e.g. when FB_ID is zero or when alpha is zero, in the future when the layer is out of CRTC bounds etc). Add a new API to make users' life simpler. Closes: https://github.com/emersion/libliftoff/issues/54
95 lines
4.2 KiB
Markdown
95 lines
4.2 KiB
Markdown
# Using libliftoff for a compositor
|
|
|
|
This document explains how to use libliftoff for a full-blown compositor.
|
|
|
|
A compositor receives buffers coming from clients and displays them on screen.
|
|
Client buffers are attached to surfaces. For instance a Wayland compositor
|
|
receives shared-memory buffers via `wl_shm` and DMA-BUFs via `wp_linux_dmabuf`.
|
|
Shared memory buffers are stored in main memory, DMA-BUFs are stored directly
|
|
on the GPU.
|
|
|
|
Compositors which can't take advantage of hardware planes will always perform
|
|
composition for all client buffers. In other words, such compositors will copy
|
|
client buffers to their own buffer, then display their own buffer on screen.
|
|
Typically the copying is done via OpenGL.
|
|
|
|
Compositors which can take advantage of hardware planes will sometimes avoid
|
|
composition (because the hardware can directly scan-out client buffers), but
|
|
sometimes they'll need to fallback to composition (because of hardware
|
|
limitations). libliftoff can help with this decision-making.
|
|
|
|
## Setting up layers
|
|
|
|
A compositor will want to create one layer per surface. That way, in the
|
|
best-case scenario, all client buffers will make it into a hardware plane and
|
|
composition won't be necessary. The layers effectively describe the compositor's
|
|
scene-graph.
|
|
|
|
The compositor will need to set standard plane properties on the buffer, in
|
|
particular the `CRTC_*`, `SRC_*` and `zpos` properties. These properties define
|
|
the position and size of the layer.
|
|
|
|
### DMA-BUFs
|
|
|
|
Each time a client submits a new DMA-BUF for a surface, the compositor should
|
|
import the buffer and update the layer's `FB_ID`. libliftoff will try to put
|
|
this layer in a plane.
|
|
|
|
### Buffers that can't be directly scanned out
|
|
|
|
Buffers using shared memory can't be directly scanned out by the hardware.
|
|
|
|
These will need to be composited, the compositor should call
|
|
`liftoff_layer_set_fb_composited`. libliftoff will never try to put this layer
|
|
in a plane.
|
|
|
|
### Elements drawn by the compositor
|
|
|
|
Sometimes compositors want to draw UI elements themselves, for instance window
|
|
decorations. The compositor could allocate buffers for these UI elements, but
|
|
sometimes it may want not to. libliftoff needs to know about this to avoid
|
|
putting a layer which is underneath in a hardware plane.
|
|
|
|
For each of those elements, the compositor can create a layer, set the `CRTC_*`
|
|
and `zpos` properties to indicate the geometry of the element, and call
|
|
`liftoff_layer_set_fb_composited` to indicate that this region needs to be
|
|
composited.
|
|
|
|
## Composition layer
|
|
|
|
A compositor must always be prepared to fallback to composition. There are a lot
|
|
of potential reasons why composition is needed, for instance:
|
|
|
|
- The client uses a buffer which can't be directly scanned out, or the
|
|
compositor wants to draw a UI element itself
|
|
- The format or modifier used by the client isn't compatible with any of the
|
|
hardware planes
|
|
- The client buffer isn't compatible with any of the planes, e.g. because of a
|
|
format or modifier mismatch
|
|
- Putting a client buffer into a hardware plane would exceed the hardware
|
|
bandwidth limits
|
|
|
|
The compositor needs to prepare a special buffer where client buffers will be
|
|
copied to if composition is necessary. Because it's not possible to know in
|
|
advance whether composition will be necessary, the compositor needs to setup
|
|
this "composition buffer" before libliftoff does its job.
|
|
|
|
The composition buffer should be allocated with a format and modifier compatible
|
|
with the primary plane.
|
|
|
|
The compositor should create a special layer, the "composition layer". The layer
|
|
should cover the whole CRTC. `liftoff_output_set_composition_layer` should be
|
|
used to tell libliftoff that composition will happen on this special layer.
|
|
|
|
If all regular layers can be put into a plane, the composition layer won't be
|
|
used. Otherwise, the compositor needs to perform the composition prior to
|
|
performing a page-flip. Each layer that didn't make it into a hardware plane
|
|
(ie. `liftoff_layer_needs_composition` returns true) needs to be composited.
|
|
|
|
## Disabling layers
|
|
|
|
When the compositor needs to hide a surface, it's not very handy to destroy the
|
|
layer (and re-create it when the surface is visible again). Instead, the
|
|
compositor can disable a layer by setting `FB_ID` to zero.
|
|
|
|
The layer will be ignored by libliftoff.
|