Commit graph

726 commits

Author SHA1 Message Date
Simon Ser
821fb28266 backend/drm: set "max bpc" property based on pixel format
Since 1d581656c7 ("backend/drm: set "max bpc" to the max") we
set the "max bpc" property to the maximum value. The kernel driver
is supposed to clamp this value depending on hardware capabilities.

All kernel drivers lower the value depending on the GPU capabilities.
However, none of the drivers lower the value depending on the DP-MST
link capabilities. Thus, enabling a 4k@60Hz mode can fail on some
DP-MST setups due to the "max bpc" property.

Additionally, it's not a good idea to unconditionally set "max bpc"
to the max. A high bpc consumes more lanes and more clock speed,
which means higher power consumption and the busy lanes cannot be
used for something else (e.g. other data transfers on a USB-C cable).

For now, let's tie the "max bpc" to the pixel format of the buffer.
Introduce a heuristic to make "high bit-depth buffer" a synonym of
"I want the best quality".

This is not perfect: a "max bpc" higher than 8 might be desirable
for pixel formats with a color depth of 8 bits, for instance when
the color management KMS properties are used. But we don't really
support that yet, so let's leave this for later.

Closes: https://github.com/swaywm/sway/issues/7367
(cherry picked from commit d36dd96e8d)
2023-01-31 17:16:59 +01:00
Simon Ser
628d601820 backend/drm: disable all CRTCs after VT switch
When the user switches away from the VT where wlroots is running,
the new DRM master may mutate the KMS state in an arbitrary manner.
For instance, let's say wlroots uses the following connector/CRTC
mapping:

- CRTC 42 drives connector DP-1
- CRTC 43 drives connector DP-2

Then the new DRM master may swap the mapping like so:

- CRTC 42 drives connector DP-2
- CRTC 43 drives connector DP-1

wlroots needs to restore its own state when the user switches back.
Some state is attached to wlr_drm_crtc (e.g. current FB), so reading
back and adopting the CRTC/connector mapping left by the previous DRM
master would be complicated (this was the source of other bugs in the
past, see [1]).

With the previous logic, wlroots merely tries to restore the state
of each connector one after the other. This fails in the scenario
described above: the kernel refuses to use CRTC 42 for DP-1, because
that CRTC is already in-use for DP-2.

Unfortunately with the legacy uAPI it's not possible to restore the
state in one go. We need to support both legacy and atomic uAPIs, so
let's fix the bug for the legacy uAPI first, and then improve the
situation for the atomic uAPI as a second step [2].

We need to disable the CRTCs we're going to switch the connectors for.
This sounds complicated, so let's just disable all CRTCs to simplify.
This causes a black screen because of the on/off modesets, but makes
VT switch much more reliable, so I'll take it.

[1]: c6d8a11d2c
[2]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3794

Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3342
2023-01-18 14:10:35 -05:00
Simon Ser
8cf1bd5582 backend/drm: fix VRR test
We were calling drm_connector_supports_vrr() before
drm_connector_alloc_crtc(). Thus, when an output is currently off,
the VRR test would always fail, because it checks that the
vrr_enabled CRTC prop exists.

(cherry picked from commit 90a6c7b7e1)
2022-12-07 15:11:46 +01:00
Simon Ser
9c54451482 backend/drm: fix FPE when disabling output
Fixes: 65836ce357 ("backend/drm: log modesetting commits")
Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3534
(cherry picked from commit a40ba16a64)
2022-11-17 09:09:35 +01:00
Simon Ser
356ac5eed9 backend/drm: log modesetting commits
(cherry picked from commit 65836ce357)
2022-11-17 09:09:35 +01:00
Simon Ser
e169ebb8cf backend/drm: log refresh rate in Hz
(cherry picked from commit b3da33116e)
2022-11-17 09:09:34 +01:00
Simon Ser
a6ff023df2 backend/drm: only request page-flip if active
It doesn't make sense to request a page-flip for a disabled output.

Fixes: 84e727daae ("backend/drm: request page-flip event on modeset")
Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3528
(cherry picked from commit f863b93c05)
2022-11-16 18:06:01 +01:00
Simon Ser
84e727daae backend/drm: request page-flip event on modeset
The old drm_connector_set_mode() function did that by calling
drm_crtc_page_flip(). We lost this in the refactoring.

Fixes: f216e97983 ("backend/drm: drop drm_connector_set_mode()")
2022-11-11 14:46:51 +00:00
illiliti
eec95e3d5e backend/drm: use pnp.ids to fetch EDID data 2022-11-09 00:25:18 +03:00
Simon Ser
d75b4d8e86 Revert "backend/drm: fetch EDID manufacturer from udev_hwdb"
This reverts commit e646d882cf.

This commit has added a dependency on udev_hwdb. This API isn't
available on all platforms (e.g. FreeBSD), and further deepens
our udev dependency. A better solution is being worked on in [1].

[1]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3638
2022-11-08 19:08:43 +01:00
Simon Ser
fc3d8b228b backend/drm: get possible CRTCs in create_drm_connector()
This stuff is immutable for a given connector.
2022-11-02 14:48:30 +00:00
Simon Ser
92580a2f67 backend/drm: extract create_drm_connector()
Move a bit more logic out of the big loop in scan_drm_connectors().
2022-11-02 14:48:30 +00:00
Simon Ser
c6d8a11d2c backend/drm: fetch current CRTC once on startup
Once we are DRM master, the CRTC cannot be changed behind our back
except during a VT switch.

After a VT switch, we try to restore whatever KMS state we had last
programmed. Reloading the current CRTC from KMS breaks this and
can result in a modeset without a FB.

Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3432
2022-10-19 00:23:18 +00:00
Simon Ser
b475190327 backend/drm: log failures in drm_surface_blit()
Can make issues like [1] easier to debug.

[1]: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3451
2022-10-18 16:39:22 +02:00
Simon Ser
a2063c93ea backend/drm: drop drm_crtc_page_flip()
Inline it in drm_connector_commit_state(). Brings us a step closer
to unifying the test code-path and the commit code-path.
2022-10-17 17:39:41 +02:00
Simon Ser
0c962c98cc backend/drm: log when restoring mode after VT switch fails
Can make it easier to track down issues.
2022-10-17 15:14:02 +00:00
Simon Ser
98a83ce14c backend/drm: fix EINVAL atomic commits after VT switch
The drm_connector_commit_state() call in handle_session_active()
was not resulting in any atomic commit, because it didn't match any
of the if branches: active = true, no new buffer was committed,
and adaptive sync/gamma LUT were unchanged. Thus the commit was a
no-op.

Later on, when the compositor performs regular page-flips, the
kernel would return EINVAL indicating that a modeset was needed.

Rework the logic to use a non-blocking page-flip commit if a buffer
was committed, and use a blocking commit if the connector is on or
is being disabled. The only case where we should skip the atomic
commit is when disabling (active = false) an already-disabled
connector (conn->crtc == NULL).

Note, 6936e163b5 ("backend/drm: short-circuit no-op commits")
has introduced early returns for other situations where we don't
need to perform an atomic commit (e.g. updating scale or transform
of an output).

Fixes: f216e97983 ("backend/drm: drop drm_connector_set_mode()")
Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3432
2022-10-17 15:14:02 +00:00
Simon Ser
ca432ea539 backend/drm: extract current mode logic into separate function
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.
2022-10-17 11:36:58 +02:00
Simon Ser
eeb7a81138 backend/drm: extract connect_drm_connector() logic
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.
2022-10-15 12:20:55 +02:00
Simon Ser
9560a7eefd backend/drm: use atomic API to fetch current connector's CRTC
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.
2022-10-14 15:13:14 +00:00
Simon Ser
0c0cea0258 backend/drm: use wl_container_of() instead of casts for wlr_drm_mode
Instead of casting a wlr_output_mode to wlr_drm_mode, use
wl_container_of() for slightly better type safety.
2022-10-13 16:11:39 +00:00
Alexander Orzechowski
ada6f104e6 backend/drm/legacy: Fix whitespace
This confused me while reading through.
2022-10-13 10:51:11 -04:00
Simon Ser
f216e97983 backend/drm: drop drm_connector_set_mode()
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.
2022-10-10 07:48:25 +00:00
Simon Zeni
694e9bbb9d backend/drm: allocate connector CRTC on lease creation
This was leading to crash in compositors if the wanted connector had no CRTC
2022-10-07 15:54:51 -04:00
Simon Ser
f4cf0a8d86 backend/drm: nuke wlr_drm_connector.desired_enabled
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.
2022-10-07 16:28:36 +00:00
Simon Ser
5a207aea72 backend/drm: drop unnecessary wlr_drm_connector.crtc checks
drm_connector_alloc_crtc() already checks this.
2022-10-07 16:09:05 +00:00
Simon Ser
0613fb0159 backend/drm: remove outdated TODO
This has been addressed in 8795dde94e ("Initialize connectors
current mode to the mode used by KMS on startup.").
2022-10-03 12:07:10 +02:00
Simon Ser
6adca4089c backend/drm: don't unconditionally set desired_enabled
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.
2022-10-03 12:04:12 +02:00
Simon Ser
651c876e79 backend/drm: fix missing wlr_output_state.allow_artifacts
Without allow_artifacts, applying the new state will fail because
it requires ALLOW_MODESET.

Fixes VT switch and disabling CRTCs.
2022-09-30 13:35:07 +02:00
Simon Ser
a0345f2854 output: add wlr_output_state.allow_artifacts
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
2022-09-30 10:58:17 +00:00
Simon Ser
0cabc83046 backend/drm: pass through mode picture aspect ratio 2022-09-22 09:38:27 +02:00
Simon Ser
800ea7d52d backend/drm: de-duplicate wlr_drm_mode creation
Introduce a function to convert a drmModeModeInfo into a new
wlr_drm_mode.
2022-09-21 01:35:30 +00:00
vanfanel
4ffc97d134 Only set max_bpc when full modesetting is being done. 2022-09-16 14:15:58 +00:00
vanfanel
8795dde94e Initialize connectors current mode to the mode used by KMS on startup. 2022-09-16 14:15:58 +00:00
Simon Ser
8c70245d5f output: fail commits if adaptive sync cannot be enabled
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.
2022-08-30 17:53:50 +00:00
Alexander Orzechowski
8bd7170fd9 Use env helpers 2022-08-22 10:18:52 -04:00
Alexander Orzechowski
ef4baea0e2 Use wl_signal_emit_mutable 2022-08-18 07:16:16 -04:00
Simon Ser
f244094682 backend/drm: drop enum wlr_drm_connector_status
We can just use libdrm's drmModeConnection enum instead.
2022-08-10 14:19:58 +00:00
Simon Ser
08973d2430 backend/drm: drop WLR_DRM_CONN_NEEDS_MODESET
- Add wlr_output.enabled checks to CONNECTED checks
- Replace NEEDS_MODESET with CONNECTED
2022-08-10 14:19:58 +00:00
Simon Ser
7b5e890e61 backend/drm: use drmModeConnectorGetPossibleCrtcs
This function has been merged in libdrm.

References: 3ee004ef52
2022-07-25 17:28:33 +00:00
Simon Ser
bd587a7f43 backend/drm: use drmModeGetConnectorTypeName
No need to manually maintain this table now.

The wlroots names and the libdrm (= kernel) names all match.

References: 50f8d51773
2022-07-25 17:28:33 +00:00
Simon Ser
1d581656c7 backend/drm: set "max bpc" to the max
"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
2022-06-19 16:55:36 +00:00
Simon Ser
1f1c0275be backend/drm: remove unused CRTC count check
drmIsKMS already checks for this.
2022-06-19 16:48:44 +00:00
Isaac Freund
5cca72958a
backend/drm: fix NULL pointer deference due to typo 2022-06-07 17:08:08 +02:00
Simon Ser
1f96f388e9 backend/drm: make serial optional
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.
2022-06-07 13:27:18 +00:00
Simon Ser
1b27d537d1 backend/drm: unconditionally set "content type" to graphics
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.
2022-06-07 13:21:21 +00:00
Isaac Freund
2b10ae62ad
backend/drm: fix check for no-op commits
Since 6936e163b, we short-circut no-op commits as an optimization.
However, the logic in the check was slightly off.
2022-06-02 20:18:16 +02:00
Simon Ser
6936e163b5 backend/drm: short-circuit no-op commits
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.
2022-06-02 11:46:31 +00:00
Simon Ser
acc6d94db0 backend/drm: make commits without a buffer blocking
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
2022-06-01 21:16:02 +02:00
Simon Ser
2563b79dc2 backend/drm: improve atomic commit flag logging
We weren't logging all of the flags, which made debugging more
difficult.
2022-05-31 09:31:16 +02:00