Hermes touches three layers that vary wildly between systems: the kernel (virtual display driver), the compositor (which must adopt and drive that virtual output), and the GPU stack (which must import and encode its frames). A configuration works only when all three cooperate, so "does Hermes run on X" has no single answer — this document records what has actually been exercised, what shares a code path with something that has, and what is known not to work.
CachyOS + KDE Plasma (Wayland) + AMD.
This is the maintainer's daily system, and it is the only configuration that is continuously exercised while features are written. It is not a statement that other systems matter less — it is the honest scope of what one person can keep verified. Everything outside that target is improved as problems are reported.
| Tier | Meaning |
|---|---|
| Verified | Exercised directly. The entry says how and when. |
| Expected to work | Shares its code path with something verified, and nothing known contradicts it. Nobody has run it. |
| Known broken | Reproduced, with the mechanism understood. |
| Untested | No information either way. |
"Expected to work" is a statement about code paths, not a promise about your machine. If you run one of those configurations, a report either way is useful.
The compositor has to do two things: adopt the virtual connector when Hermes connects it, and drive it at the mode the client negotiated. Each compositor family exposes a different protocol for this, which is why support is per compositor rather than per distribution.
| Compositor | Output activation | Status |
|---|---|---|
| KDE Plasma / KWin (Wayland) | kscreen-doctor |
Verified |
| COSMIC / cosmic-comp | wlr-output-management v4 |
Verified at protocol level |
| wlroots (sway, …) | wlr-output-management |
Expected to work |
| Hyprland / aquamarine | hyprctl output create headless + wlr-output-management |
Verified |
| Weston | none — see below | Driver verified, activation N/A |
| GNOME / Mutter | org.gnome.Mutter.DisplayConfig |
Video verified on hardware; layout, exclusive, mirror and input geometry verified against mutter 50.4 |
| gamescope | n/a (own session) | Expected to work |
| X11 | X11 capture path | Expected to work |
The development target. Output activation goes through kscreen-doctor, and
this is the only compositor where exclusive mode
(isolated_virtual_display_option) is fully supported: it disables the physical
outputs for the duration of the session, restores them when it ends, and
persists the previous layout so a crashed session can be recovered at next
startup.
Touch and pen are bound to the streamed output. KWin binds a touchscreen or
a tablet to a single output, and without a binding it guesses: the built-in
panel, an output whose physical size matches the device's, or the first output.
Hermes binds each of its touch and pen devices to the virtual output through
KWin's org.kde.KWin.InputDevice D-Bus interface as the device appears. KWin
stores that binding in kcminputrc, in a group named after the device, and
Hermes puts the previous value back when the display goes away. Writing the
older OutputName key is not enough on its own: KWin 6.7 reads OutputUuid
after it, and an empty one undoes the match. The devices of concurrent sessions
share their names, so a new client's devices follow the display activated last.
Verified on KWin 6.7.4 with uinput devices carrying Hermes' names and ids: a
touchscreen and a tablet that appear are bound to the virtual output, a later
device inherits the stored binding, and after the restore a new one is left to
KWin's guess again. Packaged builds open the standard /run/user/<uid>/bus
address explicitly when libsystemd's normal discovery fails: the package's
cap_sys_admin+p file capability enables secure-execution mode, in which
libsystemd intentionally ignores the environment variables it normally uses to
find that same bus.
Tested 2026-08-16 against the Arch cosmic-comp 1:1.3.0-1 package (the binary
self-reports 1.0.0) in a disposable virtme-ng guest, driving a Hermes-KMS card
on its DRM backend.
cosmic-comp advertises zwlr_output_manager_v1 version 4 (plus
zcosmic_output_manager_v1 v3 as an extension on top of it, not a
replacement). Hermes binds min(version, 4), so the versions match exactly and
the existing wlroots path is used unchanged — no COSMIC-specific code exists or
is needed.
Observed:
- the virtual connector appeared in the output list with its full mode set;
- COSMIC selected the mode the client requested (
1600x1068 @ 89.99 Hz) as current, because the driver marks the requested modeDRM_MODE_TYPE_PREFERRED; - the compositor rendered into the card's scanout buffer, which is what Hermes' capture reads.
Not tested: a real streaming session, and exclusive mode. Exclusive mode uses
the same wlr-output-management path, so it is expected to work.
Capture on COSMIC works only with the Hermes-KMS backend — see Capture backends.
Mutter implements neither kscreen-doctor nor wlr-output-management, only its
own org.gnome.Mutter.DisplayConfig D-Bus interface.
This was reported broken as a black screen on the client while input and audio kept working. The investigation found three independent problems, all fixed for the video path:
- Hermes asked whether Mutter had adopted the connector with a single call issued milliseconds after connecting it. Mutter adopts asynchronously, so the answer was reliably "no" and the session was declared failed.
- Mutter does adopt the connector, but at whichever mode it prefers. It drove the output at one resolution while Hermes captured at the requested one, so the encoder published frames the compositor never rendered.
- Mutter renders on the real GPU and PRIME-imports that DMA-BUF into Hermes-KMS
for scanout.
ACQUIRE_FRAMEincorrectly re-exported the imported GEM wrapper instead of returning its original DMA-BUF. The wrapper has no shmem file for the consumer to pin, so the attach failed with-EINVAL, surfaced by EGL asEGL_BAD_ALLOC. Hermes-KMS 0.3.2 returns the original DMA-BUF and carries a regression test for this imported-scanout path.
Hermes now waits for Mutter to probe the connector and pushes the requested mode
through ApplyMonitorsConfig. Because that call is all-or-nothing, every config
is submitted to Mutter's VERIFY method first and abandoned if it does not
validate, and it is applied as temporary so ~/.config/monitors.xml is never
rewritten.
The output and scanout path was exercised on 2026-08-22 in a CachyOS VM with kernel 7.1.8 and GNOME Shell/Mutter 50.4. Separately, the original reporter in #22 confirmed a working video stream on an RX 7800 XT after installing the driver fix. This verifies the video path; it does not change the exclusive-mode limitation below.
A fourth problem, on the input side, was found afterwards and is fixed. Mutter
measures an absolute pointing device against the extents of the whole stage, so
the client's coordinates need the streamed output's offset within the desktop
envelope to land on it. Hermes resolved that geometry through kscreen-doctor,
which GNOME does not implement, and only asked for it in multi-output mode. Since
the physical outputs stay on for the session here, the desktop is always
extended and the offset always matters: a 1600x1068 client stretched across the
reporter's 4160-wide desktop, so most of its screen pointed at the physical
monitor. Geometry now comes from GetCurrentState, in the logical coordinates
the pointer is actually measured in.
Whether that is the whole of the pointer behaviour reported in #22 is not established - the same description also fits the host's own mouse, which Hermes never touches - but the missing offset was real and is gone.
What was verified, and how. Every configuration described below was
submitted to a real mutter 50.4 — headless, with two virtual monitors, its
session bus exposed on a shared socket so the payloads Hermes builds could be
fed to it unchanged. Mutter accepted and applied the exclusive configuration and
left only the virtual output in the layout; accepted the mirrored one and put
both connectors in a single logical monitor; and restored the original layout
from the captured configuration in both cases. The offsets were checked against
the live logical monitors at 100% and at 200%, where the mode-size arithmetic
this replaced would have overstated the desktop by 44%. The placement fix was
checked the other way round as well: the payload the previous code would have
built is rejected by mutter with Logical monitors not adjacent, which is what
made it take the whole configuration down rather than just the placement. The
MonitorsChanged subscription was exercised with the same four match strings
the code uses, and the touch and pen settings paths were written, read back and
reset through GSettings.
Not covered by that: a real KMS session with the output on a second GPU, which
is what the copy path and the cursor plane depend on; whether GNOME's input
mapper actually routes a touchscreen to the bound monitor, which needs real
devices on a seat; and the global-scale-required branch, which headless mutter
does not exercise. The D-Bus and GSettings calls themselves were reproduced
command-for-command rather than executed through Hermes' own wrappers.
A layout change mid-session is noticed. Everything above reads the monitor
state once and acts on the answer, and GNOME rewrites the layout for reasons
that have nothing to do with streaming — another monitor plugged in, the
Displays panel opened, a stored configuration reapplied after a resume. Hermes
subscribes to MonitorsChanged over sd-bus and, when the change actually moves
an output or changes a mode, reinitialises capture so the geometry is resolved
again. It deliberately does not put the layout back: whoever changed it very
likely meant to, and the resolution the client sees follows the compositor. The
subscription needs libsystemd at build time; without it the rest still works and
a mid-session change simply goes unnoticed.
Touch and pen are bound to the streamed output. GNOME routes an absolute
pointer over the whole desktop, but binds a touchscreen or tablet to a single
monitor. Left to itself it guesses - by EDID, by the device's physical size,
and failing both a touchscreen falls back to the built-in panel - so a client's
touches landed on the laptop screen, or spread across the desktop on a machine
with no built-in panel. Hermes now writes the per-device output key for its
own virtual devices, matching the virtual monitor's EDID, and puts the key back
when the session ends. The key is addressed by the device's vendor and product
ids, which every Hermes device shares, so it is one binding per host: with
concurrent sessions it points at whichever output was activated last.
Exclusive mode works on GNOME. This was recorded here as impossible, which
was wrong. ApplyMonitorsConfig takes the complete list of logical monitors and
Mutter disables every connected monitor absent from it, so handing the desktop
to the virtual output is a configuration that names only it. Hermes captures the
layout it found first, submits the exclusive one through VERIFY before
applying it as temporary, and submits the captured layout again when the session
ends. The captured layout is also written to
$XDG_STATE_HOME/hermes/saved-mutter-layout before the monitors go dark - minus
the virtual connector, which usually no longer exists after a crash - and
replayed at the next start, so a crash mid-session cannot leave the screens off.
Mirroring works differently on GNOME than on KDE. KWin clones by overlapping the virtual output with the primary one. Mutter refuses overlapping logical monitors, and clones by putting both connectors in a single logical monitor - which it accepts only when both advertise the same mode size. So a mirrored session on GNOME runs at the physical monitor's resolution rather than the one the client negotiated, and if the virtual output does not advertise that resolution, Hermes says so and keeps the extended layout.
sway and other wlroots-based compositors expose wlr-output-management, the
same protocol and version verified on COSMIC, so the same Hermes code path
applies. The container image in packaging/container runs Hermes on a headless
sway session. They also implement wlr-screencopy, so the wlgrab capture
backend is available there in addition to Hermes-KMS.
Verified 2026-08-23 on CachyOS, kernel 7.1.8-1-cachyos, Hyprland 0.56.2-1, aquamarine 0.14.0-2.2, Radeon RX 6700 XT. Exercised through Hermes' own code path, not a mock: the output is created, the client's mode is applied and read back from the compositor, capture initialises on it at that mode, and removing the display leaves the session as it was.
Where the verification stands: a full stream to a client was completed on 2026-09-01 on Arch Linux (Omarchy), kernel 7.1.9, Hyprland 0.56.2, Intel UHD 770 plus NVIDIA RTX 4080 SUPER (driver 610.57) with Hyprland rendering on the NVIDIA card, NVENC, to a Hestia client over LAN, on the physical monitor and on a headless output alike, once screencopy buffers were allocated on the GPU the compositor renders with (see the known limitation below). The pacing question below is still open: the frame rate was not measured, and a headless output redraws on damage, so a still screen may not produce frames at the requested rate on its own.
Hermes does not give Hyprland a virtual DRM device. It asks Hyprland to create a
headless output, which Hyprland renders itself on the primary GPU — so the
question that breaks the DRM backends here, how aquamarine drives a display-only
device, never arises. The rest is the path every wlr session already takes: the
client's mode is applied with set_custom_mode over zwlr_output_manager_v1
(confirmed accepted on a headless output), and capture runs over
wlr-screencopy-unstable-v1.
Two things are worth knowing about the mechanism:
- The output is created over Hyprland's control socket
(
$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket.sock), not over any Wayland protocol, so Hermes must run inside the session — a service that cannot seeHYPRLAND_INSTANCE_SIGNATUREreports the feature as unavailable and says so. output createreplies onlyok; it does not name what it made, and theHEADLESS-Ncounter does not reset when an output is removed. Hermes learns the name by diffing the monitor list, because the second output of a session isHEADLESS-2even when it is the only one alive.
hyprctl keyword monitor — the recipe most guides use to set the mode — does
not work on a config using the non-legacy parser; it answers keyword can't work with non-legacy parsers. Use eval. That is why the mode goes through
wlr-output-management instead, which is also the path Hermes already had.
Hermes-KMS and EVDI remain unusable on Hyprland for the reasons below, so
selected_backend() routes Hyprland to the headless path regardless of the
configured backend.
Investigated 2026-08-22 on CachyOS, kernel 7.1.8-1-cachyos, Hyprland 0.56.2-1, aquamarine 0.14.0-2.2 and Hermes-KMS 0.3.0, from live session logs and a controlled reproduction. Re-checked against Hermes-KMS 0.4.0 on 2026-08-23; what changed is noted where it changed.
Hyprland is not a wlroots compositor. It has its own backend, aquamarine, so
it does not share the code path verified on sway and COSMIC — and that
difference is exactly what breaks virtual displays. The Hermes side is not the
problem: Hyprland implements zwlr_output_manager_v1, the protocol Hermes uses
to enable a virtual output, and it does adopt the connector when the driver
connects it, giving the virtual monitor its own workspace. The failure is a
layer below, in how aquamarine drives a secondary DRM device.
Stock aquamarine cannot drive a virtual display at all. In its multi-GPU
model the card holding the physical monitor becomes the primary DRM device, and
every other KMS device with an enabled output has to host its own EGL/GLES
renderer, because aquamarine renders on the primary and blits into the secondary
before scanout. A virtual display cannot host a GL renderer — Mesa has no DRI
driver for the device, so eglInitialize fails:
ERR [EGL] eglInitialize errored out with EGL_NOT_INITIALIZED: DRI2: failed to create screen
ERR CDRMRenderer: fail, eglInitialize failed
ERR drm: initMgpu: no renderer
ERR drm: Failed to initialize renderer backend for blitting
The connector appears and the modeset succeeds, but every commit fails at the
blit stage and no frame is ever presented — a black output while Hyprland
retries each frame. One session logged 653 blit failures and 969 initMgpu: no renderer.
Exposing a render node does not help, and is what makes the failure loud rather
than silent. Hermes-KMS has one because its capture channel needs it, so
aquamarine selects it and fails at eglInitialize instead of skipping the
device. EVDI, which has no render node, produces the symmetric warning and is
equally unusable.
Remove the blit and page-flip pacing fails instead. A locally patched aquamarine that imports the primary GPU's buffer over PRIME and scans it out directly — the KWin/GNOME model — does present frames, and then stalls. Over a three-minute controlled run the driver's frame sequence advanced 149 times, about 1 fps where 60 was requested, before commits stopped being accepted at all:
ERR drm: Cannot commit when a page-flip is awaiting
aquamarine arms a pending flip on every buffer commit and refuses the next one until the page-flip event arrives. Nothing in the log shows a stale event being discarded, so either the event never reaches it, or the arm/deliver cycle desynchronises and its scheduler never sees the flip.
The leading suspect was the driver's own software vblank: Hermes-KMS 0.3.0 drove
it from a hand-rolled hrtimer, and hrtimer_forward_now() skips missed periods
without calling drm_crtc_handle_vblank() for each one — under load, exactly the
sparse flips observed.
That suspect no longer exists. Hermes-KMS 0.4.0 moved the timer to the DRM
core helpers (DRM_CRTC_VBLANK_TIMER_FUNCS plus a handle_vblank_timeout hook);
the manual hrtimer path is gone. The wedge has not been retested against
0.4.0, so its status is now genuinely unknown rather than suspected — and since
the headless path made Hyprland work without answering this, nothing has forced
the question. Anyone picking it up starts from a controlled hermes-kmsctl hold
run on 0.4.0, not from the 0.3.0 evidence above.
Smaller gaps, none fatal on their own. The Hermes-KMS CRTC carries only a mode, a primary plane and a cursor, so everything Hyprland commits beyond that fails. All four were re-checked against 0.4.0 and all four are still absent:
| Missing | Effect |
|---|---|
CTM |
Hyprland's colour management commits a matrix on every state commit, even the identity one, so failed to commit ctm: no ctm prop support repeats per commit rather than per modeset |
GAMMA_LUT / DEGAMMA_LUT |
Couldn't get the gamma_size prop; no gamma control, so hyprsunset cannot work on the virtual output |
VRR_CAPABLE, HDR_OUTPUT_METADATA, Colorspace, syncobj |
reported unsupported at probe — no VRR, HDR or explicit sync |
IN_FORMATS |
the primary plane advertises no modifier blob, so only implicit linear is available |
The synthetic EDID is rejected as well: aquamarine parses it with
libdisplay-info, which is stricter than KWin's parser, so hyprctl monitors
shows the virtual output with empty make, model and serial. Cosmetic, but it
applies to any libdisplay-info consumer, not only Hyprland.
Streaming an ordinary physical display should be unaffected —
zwlr_screencopy_manager_v1 is present, so the wlgrab backend is available —
but no full session has been run that way.
What would fix it. On the aquamarine side: keep a direct import-and-scanout
path for secondary devices that cannot render, and make the flip handshake
tolerate a software vblank instead of wedging on frameInFlight. On the driver
side: add no-op CTM and gamma properties so the colour pipeline stops erroring
on every commit, and re-measure the flip handshake now that the vblank timer is
the core one.
None of this blocks streaming on Hyprland any more — the headless output above does not go through a DRM device at all. It matters for using Hermes-KMS itself under Hyprland, which is what the multi-session and seat-isolation features are built on: those still need KDE, GNOME, a wlroots compositor, or Hermes' per-session gamescope path.
Hermes-KMS ships a VM test that runs real Weston DRM compositors on its cards,
so the driver is known to work as a DRM device under Weston. Weston does not
implement wlr-output-management, so Hermes has no way to activate the virtual
output there — it would have to be configured by other means. Weston is used as
a driver test harness, not as a supported streaming session.
Distribution matters less than compositor and GPU. It determines how the kernel module is built and how the package is installed.
| Distribution | Status | Notes |
|---|---|---|
| CachyOS / Arch | Verified | Development target. In-tree PKGBUILDs. |
| Debian / Ubuntu | Expected to work | One .deb per supported LTS (24.04, 26.04), built in CI; not exercised as a desktop. Match the ubuntuNN.NN in the filename to your release. |
| Fedora | Expected to work | One .rpm per supported release (43, 44), built in CI; not exercised as a desktop. Match the .fcNN in the filename to your release. |
| Bazzite / Silverblue / SteamOS | Partial | See below. |
DKMS cannot work on ostree/bootc systems: it rebuilds the module on the running
system whenever the kernel changes, and there /usr is read-only at runtime, so
that moment never comes. Hermes-KMS ships a Containerfile that builds the
module into the image instead, compiling against the image's kernel and
installing it to /usr/lib/modules/<kver>/extra, with optional MOK signing.
Separately, packaging/container holds a runtime image that runs Hermes on a
headless sway session with audio and XWayland.
| Vendor | Encoder | Capture path | Status |
|---|---|---|---|
| AMD RDNA2 (Navi 2x) | VAAPI | Zero-copy DMA-BUF import | Verified on the development system |
| AMD RDNA3 (Navi 3x) | VAAPI | Zero-copy DMA-BUF import | Verified on RX 7800 XT (Navi 32) |
| Intel | VAAPI | Zero-copy DMA-BUF import | Expected to work |
| NVIDIA | NVENC | CPU copy | Contributed, see below |
| any | software | either | Fallback |
The zero-copy path is validated with XRGB8888, linear. NV12/P010 and HDR are
not validated.
The RX 7800 XT failure reported in #22
was the GNOME/Mutter imported-scanout bug described above, not a GPU-generation
limitation. The decisive control imported the same geometry from a plain
udmabuf on the same card, kernel and Mesa stack; that succeeded both with and
without explicit modifier attributes. After Hermes-KMS returned the original
DMA-BUF, the reporter confirmed that video streaming worked.
This is direct confirmation for Navi 32, not a claim that every RDNA3 model has been exercised. No RDNA3-specific failure is currently known, so the dedicated hardware-testing request in #23 has been retired.
NVIDIA needs a CPU copy. NVIDIA's EGL import of the driver's system-memory
DMA-BUFs reads the wrong pages beyond the first ones, so NVENC sessions capture
through a CPU copy of the scanout buffer and feed the regular RAM-to-CUDA upload
path, at the cost of one memcpy per frame. The copy waits on the framebuffer's
exported write fence and brackets the read with DMA_BUF_IOCTL_SYNC. VAAPI is
unaffected and keeps the validated zero-copy import.
A purpose-built DRM/KMS driver. The compositor owns the card and scans out the desktop; Hermes opens its render node and pulls each frame as a DMA-BUF. No DRM master and no KMS access are needed, so it coexists with the compositor.
Requires the module loaded with initial_enabled=0 and its card left on the
active seat.
Capture goes through a CPU-side buffer filled by libevdi.
EVDI exposes no render node (confirmed 2026-08-16: an EVDI-only system has
card0/card1 and zero renderD* nodes). On a normal desktop this is
irrelevant, because the compositor renders on the real GPU and treats EVDI as an
output-only device. It does mean EVDI cannot be the only DRM device in a system
— a compositor with no other GPU has nothing to render with. Hermes-KMS does
expose a render node and does not have this constraint.
An EVDI connector also reports disconnected until a userspace client calls
evdi_connect with an EDID; the card existing is not enough.
| Backend | Protocol / mechanism | Works on |
|---|---|---|
| Hermes-KMS | ACQUIRE_FRAME ioctl on the render node |
Any compositor — no Wayland protocol involved. Capturing is universal; getting a compositor to draw on the device is not — see Hyprland |
| EVDI | libevdi CPU buffer |
Any compositor, with the same caveat |
wlgrab |
wlr-screencopy-unstable-v1 |
wlroots, KWin, Hyprland — not COSMIC. This is the capture path for a Hyprland headless output |
kmsgrab |
DRM/KMS | needs DRM master or suitable permissions |
x11grab |
X11 | X11 sessions |
cosmic-comp does not implement wlr-screencopy; it implements
ext-image-copy-capture-v1 instead, which Hermes does not currently support. On
COSMIC, use the Hermes-KMS backend, whose capture involves no Wayland protocol
at all and is therefore unaffected.
A stale /etc/modprobe.d/hermes-kms.conf silently wins. The package installs
its default to /usr/lib/modprobe.d/hermes-kms.conf, but /etc/modprobe.d
overrides /usr/lib/modprobe.d. An initial_enabled=1 written there by an older
package, or by hand, keeps the virtual connector connected at boot before Hermes
owns it, and the compositor extends the desktop onto a black output nobody is
streaming. No upgrade can fix this, because the package does not own that file.
The package reports it on install and upgrade and the driver logs a warning at
probe; neither rewrites the file. Remove it, or set initial_enabled=0.
A virtual display is selected by name, and the name comes from xdg_output.
wlgrab matches the compositor's output name against the one Hermes recorded
when it created the display. Until 2026-08-23 the names were read after the
match ran, so every by-name selection failed with "is not enabled by the
compositor" for an output the same log had just listed. Only the Hyprland
headless path selects by name — a physical monitor is selected by index — so
this never surfaced before. Fixed; noted here because the error message points
at the compositor and the fault was Hermes'.
On a multi-GPU host, Wayland screencopy capture allocates on the GPU the
compositor renders with. The render-node scan used to keep the first node that
could allocate a buffer, and on an Intel + NVIDIA desktop with Hyprland on the
NVIDIA card that was the Intel iGPU; Hyprland refused the buffer with a fatal
zwp_linux_buffer_params_v1 protocol error that nothing read, and the client got
a black stream with working audio and input. The compositor's device now comes
from linux-dmabuf default feedback (protocol v4 and later); on a compositor below
v4 the scan still runs, and adapter_name = /dev/dri/renderDNN names the right
card by hand.
Absolute input on a wlroots-style compositor is mapped in the compositor's
logical space. Hyprland and its relatives spread an absolute pointer device
across the bounding box of all outputs in logical (scaled) pixels, so on a
scaled desktop with a physical monitor and a virtual display both active the
streamed output's offset and the envelope are taken from xdg_output's logical
layout and expressed in the streamed output's own pixels, the same way the
GNOME path reads Mutter's logical monitor layout. KMS capture of a physical
monitor at a scale other than 1 still has the old mismatch.
The development udev rule hides the card from every compositor.
udev/99-hermes-kms-ignore-seat.rules strips TAG+="seat" and ID_SEAT from
the Hermes-KMS card so an isolated test session can claim it. With that rule
installed no compositor adopts the virtual output — KWin, Hyprland or any other
— which is usually reported as "the virtual display never appears at all". The
rule is for isolated testing only; remove it for streaming.
Portrait modes above 2160 px tall are rejected. The driver caps geometry at
HERMES_KMS_MAX_WIDTH 3840 by HERMES_KMS_MAX_HEIGHT 2160, so a client asking
for a portrait mode such as 1440x2560 fails validation with -EINVAL. This
affects tablets and phones streaming in portrait orientation.
Exclusive mode is implemented for KDE, GNOME and wlroots. See GNOME / Mutter. On Hyprland the question does not arise: the headless output is not a DRM device — see Hyprland.
Confined packaging may lose output management. COSMIC filters privileged
protocol globals by Wayland security context; clients without a security context
are trusted. Hermes running as a normal user service qualifies, but a Flatpak or
Snap build could be filtered out and would not see wlr-output-management.
COSMIC mirroring reports an enabled output without a current mode (pop-os/cosmic-comp#945), which may affect the layout Hermes saves before entering exclusive mode.
Keeping several distributions, compositors and GPU stacks working is not something one maintainer can do alone, and most of what is listed above as "expected to work" only becomes "verified" when someone runs it and says what happened. Issues and pull requests are very welcome — including reports that something simply works, which are as useful as bug reports for moving an entry between tiers.
A useful report includes:
- distribution, kernel, compositor and its version, GPU and driver;
XDG_CURRENT_DESKTOPandXDG_SESSION_TYPE;- the Hermes log for the failing session;
cat /sys/class/drm/card*/statusand, if the module is loaded,cat /sys/module/hermes_kms/parameters/initial_enabled;- for display-adoption problems, the compositor's view of its outputs
(
kscreen-doctor -o,wlr-randr, or Mutter'sGetCurrentStateover D-Bus).
| Previous | Next |
|---|---|
| Getting Started | Changelog |