Runtime display selection in DRM backend#2197
Draft
matte-schwartz wants to merge 4 commits into
Draft
Conversation
…election
Add runtime display output selection to gamescope-control. Previously the
output was only selectable via --prefer-output at startup, which is not
adjustable in gamescope-session.
The interface adds available_display_info / available_display_info_done
events to enumerate the connected outputs a client can switch to,
set_display / unset_display requests to pick one by connector name or
fall back to --prefer-output, and a matching set_display console command
taking either an exact connector name or a make/model/serial substring.
Displays are tracked as follows: the connector name is authoritative for
the actual switch (as --prefer-output already is), but a connector number
can't always be relied upon as a stable identifier. Connectors have a
possibility to be reenumerated when a cable is replugged, across reboots,
or on MST topology changes, so what was DP-1 may become DP-4. This also
depends on what type of device and dock/cable are being used. Instead,
the selection is persisted by an EDID-derived identifier, "{make} {model}
{serial}", and resolved identifier-first. Among the connected outputs,
the one whose identifier matches is chosen, so the monitor is found
regardless of its current connector.
One corner case is that physically identical, serial-less monitors could
collide as the same identifier. In this case, a " [connector]" suffix is
appended, and matching falls back to the connector as a secondary key
where the hinted connector wins if present.
The available-display list also flags the output currently being driven
(a "current" display flag), so a client can show which display is active,
including which of two otherwise-identical monitors.
With this in mind, the expected user experience should be consistent
across multiple scenarios:
- Desktop setups: connectors are stable across boots, so identical
monitors are individually selectable and the choice persists.
- Handheld connected to dock: connectors may reenumerate on replug, so
the EDID identifier carries the selection across regardless of how the
connectors come back.
display_selection is implemented in its own header in order to support
tests. I've also been able to test this on a Steam Deck with third-party
dock, a 7900XTX, an RTX 5090, and an Intel Lunar Lake APU with a Steam
Deck dock to confirm that all scenarios behave as expected.
Physically identical, serial-less monitors collide on the same EDID
identifier, so the selection key falls back to a " [connector]" suffix to
tell them apart. However, the connector name keys on connector_type_id,
which the kernel reassigns when the MST sink connectors are torn down and
recreated on reprobe, so the selection jumps around unexpectedly.
Instead, read the DRM MST PATH blob ("mst:<conn>-<port>") and use it as
the tiebreak hint when present. The port numbers are topology-derived
(which port of the dock the sink hangs off), and the "mst:" prefix is the
upstream connector id, which is fixed at output setup and not re-init'd on
a downstream reprobe. So the PATH survives the connector renumber that
connector_type_id does not. Non-MST and single-stream connections have no
PATH and fall back to the connector name as before.
…splay Until Steam learns about GAMESCOPE_DISPLAY_SELECTION_FILE, write it from both setter paths (drm_set_preferred_connector for the protocol/CLI path, drm_set_preferred_display_identifier for the GAMESCOPE_DISPLAY_PREFERRED_IDENTIFIER xprop path) so runtime selections stick across restarts regardless of which channel set them. Revert once Steam owns the writes.
Author
|
I'm about to leave on vacation for a few days, but my goal is to finish up testing and undraft this sometime next week. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The goal for this PR is to provide runtime controls to select a preferred display in the DRM backend without relying on the commandline argument -O. The exact details are explained in the commits, but generally this is what's expected:
you can also run
gamescopectl set_display <connector name>rather than substrings of the monitor identifiers. the choice from Steam is meant to be written to~/.config/gamescope/display.cfg, similar tomodes.cfg, but[HACK] DRMBackend: Temporarily write preferred-display file on set_displaymoves this write into gamescope for testing purposes:there is an xatom path for this as well:
tests are included so it was easier to check the code around some of the weird edge cases. this is also why display_selection.h is its own header file, to pull into the testing framework.
marked as draft for now so additional testing can be done, but before bringing it out of draft I will drop hack commit.