Extract the logic to fetch the current mode to a separate function
to make it more readable. Stop dying in an assert when
get_drm_prop_blob() fails. Always make it so the drmModeModeInfo
pointer is allocated so that we can free() it unconditionally.
We already have disconnect_drm_connector() to handle the
CONNECTED → DISCONNECTED transition. Let's add
connect_drm_connector() to handle DISCONNECTED → CONNECTED. This
makes scan_drm_connectors() shorter and easier to follow.
No functional change, literally just moving code around.
We were using the legacy API (with a detour through drmModeEncoder)
to find out the current CRTC for a connector. Use the atomic API
when available.
Also extract the whole logic into a separate function for better
readability, and better handle errors.
Instead of special-casing modesets, we can just cut the wrapper
and directly call drm_crtc_page_flip(). drm_connector_test() should
already have the checks previously done in drm_connector_set_mode(),
all we need to do is update enabled/mode after a successful atomic
commit.
This field becomes stale too easily: for instance, see 6adca4089c
("backend/drm: don't unconditionally set desired_enabled").
Additionally, drm_connector_alloc_crtc() needs to do some weird
dance, restoring its previous value.
Instead, add a connector arg to realloc_crtcs() to indicate a new
connector we want to enable.
We were unconditonally setting desired_enabled = true for all
connected connectors. This makes realloc_crtcs() always keep a CRTC
active for these, even if the user doesn't want to enable them.
When starting up, the compositor might call wlr_output_set_mode()
with a mode which is already the current one. wlroots will detect
this and make the wlr_output_set_mode() call a no-op. During the
next wlr_output_commit() call, wlroots will perform an atomic
commit without the ALLOW_MODESET flag.
This is an issue, because some drivers need ALLOW_MODESET even if
the mode is the same. For instance, if the FB stride or modifier
changed, some drivers require a modeset.
Add a new flag "allow_artifacts" which is set when the compositor
calls mode-setting functions. Use this flag to figure out whether
we want to perform atomic commits with ALLOW_MODESET.
(The name "allow_artifacts" is picked because ALLOW_MODESET is a
misnomer, see [1].)
[1]: https://patchwork.freedesktop.org/patch/505107/
Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3499
Previously, adaptive sync was just a hint and wouldn't make any
atomic commit fail if the backend didn't support it. The main reason
is wlr_output_test wasn't supported at the time.
Now that we have a way for compositors to test whether a change can
work, let's remove the exception for adaptive sync and convert it to
a regular output state field.
"max bpc" is a maximum value, the driver is free to choose a
smaller value depending on the bandwidth available.
Some faulty monitors misbehave with higher bpc values. We'll add
a workaround if users get hit by these in practice.
References: https://gitlab.freedesktop.org/wayland/weston/-/issues/612
The EDID 1.4 spec says that the serial number is optional:
> If this field is not used, then enter “00h, 00h, 00h, 00h”.
Leave the wlr_output.serial field NULL in that case, and hide it
from the output description.
CTA-861-G says that "graphics" is used to indicate non-analog (ie,
digital) content. With that bit set, the sink should turn off analog
reconstruction and other related filtering.
Some output commits (changing e.g. the output scale or transform)
don't require any change in the KMS state. Instead of going through
a KMS commit, return early. Blocking KMS commits can be expensive.
The wlr_output API requires compositors to wait for wlr_output.frame
before submitting a new buffer. However, compositors can perform a
commit which doesn't involve a buffer anytime.
If the commit is a modeset, we set DRM_MODE_ATOMIC_ALLOW_MODESET and
block until the commit is done. If it isn't, we currently always
perform a non-blocking commit. This is an issue because a previous
page-flip might still be in flight kernel-side, returning EBUSY.
Fix this by using blocking commits when a buffer isn't submitted by
the compositor.
Closes: https://github.com/swaywm/sway/issues/6962
References: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/2239
This allows the make/model/serial to be NULL when unset, and allows
them to be longer than the hardcoded array length.
This is a breaking change: compositors need to handle the new NULL
case, and we stop setting make/model to useless "headless" or
"wayland" strings.
Prior to [1], if an entry in a DRM format set was different than a
single LINEAR modifier, implicit modifiers were always allowed. This
has changed and now implicit modifiers are only allowed if INVALID
is in the list of modifiers.
So now we can safely enable explicit modifiers for cross-GPU imports,
without risking receiving buffers with an implicit modifier. This
should improve perf a bit on setups where two GPUs from the same vendor
are used.
This fixes the first bullet point from [2].
[1]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3231
[2]: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3331
Maintaining our internal table up-to-date is tedious: one needs to
manually go through the PnP ID registry [1] and check whether we're
missing any entry.
udev_hwdb already has an API to fetch a manufacturer name from its
PnP ID. Use that instead.
[1]: https://uefi.org/pnp_id_list
wlroots picks names for all outputs, but it might be desirable for
compositor to override it.
For instance, Sway will use a headless output as a fallback in
case no outputs are connected. Sway wants to clearly label the
fallback output as such and label "real" headless outputs starting
from HEADLESS-1.
drmModeAddFB2 doesn't support explicit modifiers. Only accept INVALID
which indicates an implicit modifier and LINEAR which may indicate
that GBM_BO_USE_LINEAR has been used.