Commit graph

363 commits

Author SHA1 Message Date
Sc4r3Cr0w
f5cdaa8801
drm: CRTC starvation recovery + clear stale page-flip state after suspend (#254)
* drm: handle CRTC starvation recovery when outputs are disabled

When more displays are connected than CRTCs available, connectors that
arrive after all CRTCs are claimed become starved.  The compositor can
free a CRTC by disabling an output, but nothing reclaimed that CRTC for
the starved connector.

Restructure recheckCRTCs() into two passes: first, disabled outputs
release their CRTCs and enabled connectors get priority assignment;
second, any remaining free CRTCs are given to disabled connectors as
backup slots for quick re-enable.

When applyCommit() detects an enabledState transition, schedule
recheckOutputs() via addIdleEvent so starved connectors pick up the
freed CRTC on the next event loop iteration, without reentrancy or
blocking the event loop.

* drm: clear stale page-flip state after suspend/resume

My laptop (i915, 3 external monitors) would go permanently black after
S3 or suspend-then-hibernate. The only recovery was a hard restart.

The root cause: when display hardware powers off during suspend, any
in-flight page-flip completion event is lost. handlePF() never fires,
so isPageFlipPending stays true from the last frame before suspend. On
resume, scheduleFrame() sees the stale flag and bails, commitState()
rejects every frame with "Cannot commit when a page-flip is awaiting",
and nothing ever clears it. Screens stay dark forever.

VT switch doesn't hit this because the kernel preserves DRM state and
queues pending events in the fd buffer. Suspend kills the hardware, so
there's nothing to deliver.

Fix in two places:

1. restoreAfterVT(): clear isPageFlipPending, isFrameRunning, and
   frameEventScheduled for all connectors before recheckOutputs(). For
   VT switch this is harmless (the events arrive anyway and handlePF
   would set them false). For suspend it unblocks frame scheduling.

2. commitState(): record a CLOCK_BOOTTIME timestamp when
   isPageFlipPending is set. If a modeset finds a flip pending for
   >500ms (well past any vblank), treat it as stale and clear the
   flags. CLOCK_BOOTTIME instead of CLOCK_MONOTONIC because MONOTONIC
   freezes during suspend on Linux, making elapsed time look like zero
   after resume.

Timestamp recorded in both atomic and legacy commit paths.

Relates to Hyprland#8312, Hyprland#6289.

---------

Co-authored-by: j4kuuu <j4kuuu>
2026-04-27 21:02:14 +01:00
cd8321eba2
version: bump to 0.11.0 2026-04-26 00:25:11 +01:00
648a13d0ee
headless: hold ref in next frame timer 2026-04-22 17:45:44 +01:00
b3ea868665
headless: verify fn is valid before calling 2026-04-22 17:45:44 +01:00
Visal Vijay
9a1ca6b8cb
internal: avoid repeated vector access in backend and DRM loops (#281) 2026-04-20 17:33:07 +01:00
d5ab4fdd25 CI: use org-wide actions 2026-04-17 14:35:26 +03:00
Marcello Haddeman
981132ce0b
libinput: method to get libinput_tablet_tool from ITabletTool (#278)
* libinput: method to get `libinput_tablet_tool` from ITabletTool

Libinput has some configuration specific to the tablet tool that could
be interesting to set for Tablet users. However there's currently no
way of getting the required `libinput_tablet_tool` ptr from
`ITabletTool`. Meaning it's not possible to build the configuration on
Hyprland (or anything else using aquamarine).

This change adds the virtual function `getLibinputTool()` to
`ITabletTool` as well as an implementation for `CLibInputTabletTool`

* Run clang-format
2026-04-16 18:18:49 +01:00
Visal Vijay
24f1db3c06
drm: guard logging in connector disconnect to avoid null dereference (#274) 2026-04-11 15:21:51 +01:00
Visal Vijay
1d50986c1e
backend: handle unhandled libinput switch enum with default case (#273) 2026-04-11 15:08:02 +01:00
Linux User
7371b669b2
backend: include algorithm header (#269)
Fixes error `no member named 'stable_partition' in namespace 'std'` on llvm/musl
2026-04-07 11:46:50 +01:00
e92655932d
drm: revert "reduce duplicated code in render creation (#247)"
This reverts commit ed26bdbab9.

Breaks apple, see https://github.com/hyprwm/aquamarine/issues/260
2026-04-04 19:19:43 +01:00
Pericle Purple AZ
f62a4dbfa4
backend/drm: fix multi-GPU buffer import failure during restoreAfterVT (#263)
* drm: remove an unnecessary reset after VT switching (#223)

I've tested DPMS and different monitor modes with this change, and
everything seems to be working exactly as expected.

* backend/drm: skip direct buffer import on multi-gpu during restore

---------

Co-authored-by: Mason Davy <54364725+Nosamdaman@users.noreply.github.com>
2026-03-22 20:29:50 +00:00
umbrageodotus
d67142c8c0
backend/headless: Improve and optimize timer FD logic (#258)
* backend/headless: improve timer FD deadline logic

Fixes increased timer latency, etc.

* backend/headless: increase precision of frame scheduling and clean up code

* backend/headless: fix code not compiling and skill issue

* backend/headless: fix typo

* backend/headless: improve code quality

* backend/headless: fix timer desync in scheduleFrames

* backend/headless: formatting

* backend/headless: fix buffer size in dispatchTimers (and optimize the function to be O(n) rather than O(n*n))

* backend/headless: fix build
2026-03-17 12:04:08 -04:00
8ed71bb83d
drm: revert "fallback to first render node for non-standard buses (#237)"
This reverts commit 1dbbba659c.

See #260, breaks M1/M2, potentially more split-node drivers.
2026-03-17 11:59:23 -04:00
Matthew Wong
43f10d2439
drm: re-send ctm blob on modeset (#256) 2026-03-13 16:12:56 -05:00
023eed5c9b
README: drop todo list 2026-03-05 13:15:49 +00:00
b90396425a
backend/headless: implement FPS caps for headless outputs
fixes #206
2026-03-05 13:14:52 +00:00
5d2cb726b1
flake.lock: update 2026-03-02 16:11:18 +02:00
0aba5246b5
nix: separate overlay with deps 2026-03-02 16:11:18 +02:00
25496568e4
treewide: alejandra -> nixfmt 2026-03-02 16:11:18 +02:00
Deepak Meena
1dbbba659c
drm: fallback to first render node for non-standard buses (#237)
Signed-off-by: Deepak Meena <who53@disroot.org>
Co-authored-by: Tom Englund <tomenglund26@gmail.com>
2026-02-28 15:27:25 +00:00
fazzi
1aa8490166
drm/renderer: glFlush when clearing buffers (#252) 2026-02-27 10:35:28 +00:00
Tom Englund
7f9eb08770
output: add a pendingPageFlips() method (#251)
add a way to get if there are pending pageflip so the compositor can
delay its commits.
2026-02-20 17:56:11 +00:00
Tom Englund
ed26bdbab9
drm: reduce duplicated code in render creation (#247)
initMgpu already does build gl formats so remove the temp creation of
allocator and renderer in onReady() that only built glformats,
also if guard the creation of renderers and allocators to make it less
likely to recreate one that is already existing.
2026-02-19 00:26:56 +00:00
Matt Prestlien
6d0209205a
drm: re-send HDR metadata blob on modeset (#250)
After a VT switch or sleep/resume, the kernel discards all DRM property
blobs. restoreAfterVT() rebuilds the atomic commit with the in-memory
HDR metadata, but prepareConnector() skips blob creation because
STATE.committed (the "what changed" bitmask) was cleared after the last
pre-sleep commit.

During a modeset the kernel state is fully reset, so all properties must
be re-sent regardless of the committed flags. Add a data.modeset guard
to bypass the committed check, matching how max_bpc, colorspace, and VRR
are already handled unconditionally.

The existing has_value() check prevents false positives: non-HDR
modesets (resolution changes etc.) don't populate data.hdrMetadata, so
the block is still skipped.
2026-02-17 13:52:38 +00:00
Lee Bousfield
8a0eb4f0a7
drm/renderer: split input and output buffer attachments (#249) 2026-02-17 13:51:31 +00:00
Tom Englund
603f5cdd42
drm: make pageflips drive the frames (#241)
make the pageflips drive the frames instead of waiting on the idle
dispatch, it adds unnecessery latency at the beginning of each frame.
2026-02-15 21:47:41 +00:00
André Silva
a494d50d32
backend: fix use-after-free of logger during teardown (#244) 2026-02-12 11:24:34 +00:00
Andrei Sabalenka
b2f6c1a838
drm: keep secondary renderers alive only when they're needed (#239)
Currently aquamarine initializes all the secondary renderers and keeps them alive all the time, even when no output on that GPU is enabled. Keeping a secondary renderer alive prevents unused GPU from powering down completely, which e.g. makes battery life significantly worse on Optimus laptops with DP/HDMI ports wired to dGPU.

This patch initializes secondary renderers only when at least one connected output is enabled, and deinitializes them when no enabled outputs remain.
2026-02-12 01:05:18 +00:00
Kevin McConnell
b91f570bb7
drm: ignore redundant tiled display connectors (#238)
Some high-resolution displays (e.g. Apple Studio Display 5K) expose
multiple DRM connectors in a tile group. However, when the driver
handles tiling internally, a single connector will advertise the full
panel resolution, and its other connectors will be inoperative and
redundant.

To avoid ghost outputs from those dead tiles, we can filter out any
tiles where there is a connector in that group that offers the full
resolution by itself.
2026-02-06 21:01:40 +00:00
Deepak Meena
35fa4a965e
drm: use parent device matching for render nodes (#235)
* drm: use parent device matching for render nodes

Signed-off-by: Deepak Meena <who53@disroot.org>

* Revert "rendernode: dont bother finding one on evdi"

This reverts commit 81a0ddf42f.

---------

Signed-off-by: Deepak Meena <who53@disroot.org>
2026-02-04 01:01:29 +00:00
Tom Englund
2455556b42
drm: minor AMS fixes (#229)
* atomic: properly check min max bpc values

properly use maxBpcBounds[0] and clamp it in getMaxBpc. lets not go
below or beyond what HW supports.

* atomic: actually set blobid in prepareGammaBlob

set blobid to zero and not the local copied pointer.

* atomic: add hdr blob to apply and rollback aswell

add missing hdr blob to apply and rollback.

* drm: dont leak modeinfo

free currentModeInfo when done with it.
2026-01-31 13:39:54 +00:00
Tom Englund
af4c6fedbe
renderer: set EGL_CONTEXT_RELEASE_BEHAVIOR_KHR if supported (#234)
EGL_CONTEXT_RELEASE_BEHAVIOR_KHR determines what happends with implicit
flushes when context changes, on multigpu scenario we change context
frequently when blitting content. while we still rely on explicit sync
fences, the flush is destroying driver optimisations.

setting it to EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR essentially mean
just swap context and continue processing on the next context.
2026-01-30 19:42:14 +00:00
Tom Englund
def5e74c97
backend: read idle timer (#233)
* backend: read idle timer

the manpage for timerfd_create and read states this.

timefd_create creates a new timer object, and returns a file descriptor
that can be used to read the number of expirations that have occurred.

The FD becomes readable when the timer expires.

read removes the “readable” state from the FD.

so most likely it has somewhat worked because of the updateIdleTimer()
function.

* backend: check if fd is readable log otherwise

ensure we dont accidently trigger some blocking read call on a non
readable fd, log an error if this occurs, else read it.
2026-01-26 11:59:18 +00:00
Tom Englund
534c88e2f2
drm/formats: add drmModifierToName and print names (#230)
* modifiers: add drmModifierToName and print names

makes it easier to parse logs.

* modifiers: print both uint and name

print both the uint and name
2026-01-06 00:02:53 +01:00
Maxime Nordier
b8a0c5ba5a
libinput: fix pad groups not being ref'd (#227)
Without refing pad groups they would get destroyed when the current
event gets out of scope, causing a segfault when destroying a
CLibinputTabletPad.
2025-12-29 17:15:02 +01:00
Tom Englund
96b53bcb42
output: fix degammalut typo (#226)
dont overwrite gammalut when setting degammalut
2025-12-28 13:34:24 +01:00
Mason Davy
d83c97f8f5
drm: remove an unnecessary reset after VT switching (#223)
I've tested DPMS and different monitor modes with this change, and
everything seems to be working exactly as expected.
2025-12-16 15:56:36 +00:00
Molyuu
c6354f54f9
drm: convert vd path before compare with explicit device path (#222)
FreeBSD always returning symbolic links '/dev/dri/card*' pointed to '/dev/drm/*',
so output device will never be found if `AQ_DRM_DEVICES` is set as explicit devices
path is converted to canonical file path.
2025-12-13 16:40:59 +00:00
a43bedccec
backend: move logger to backend 2025-12-02 22:20:51 +00:00
zacoons
561ae7fbe1
backend: add freeDrmDevice on error in initDmabuf (#221)
This may have caused a small memory leak in some cases.
2025-11-28 22:58:30 +00:00
a20a0e67a3
version: bump to 0.10.0 2025-11-23 18:33:09 +00:00
23e4e25dd3
backend: implement hyprutils' cli::logger 2025-11-23 16:57:12 +00:00
André Silva
6d0b356758
drm: prevent nullptr deref during DRM backend shutdown (#218) 2025-11-05 15:31:59 +00:00
Tom Englund
62479232aa renderer: drop the mods.empty() check
what if the driver did return modifiers that isnt linear, this wont be
added because of the .empty check.
2025-10-25 20:34:59 +01:00
Tom Englund
79b515fc44 renderer: use array and EGLint in creating image
lets use array and eglint in creating eglimage reduces vector
reallocations and unnecessery casting of data.
2025-10-25 20:34:59 +01:00
1826a99238
wayland: send commit after frame 2025-10-10 14:06:57 +01:00
jaro
3b3d8a8bde
drm: ensure disconnect called for removed connectors (#215)
Originally disconnected monitors were not removed from hyprland
correctly and duplications were created when an external monitor was
reattached leading to invalid behavior when switching
(empty desktop is visible).

Now removed monitors are explicitly disconnected during connectors
scanning.
2025-10-07 13:44:35 +02:00
Tom Englund
81a0ddf42f rendernode: dont bother finding one on evdi
evdi/displaylink devices doesnt give us a rendernode at all, and asahi
was hard to associate if a rendernode was related to the
displaynode/card so we fallback to just first found if that occurs.
might be more appropiate to figure out a proper way to deal with these
cases then workaround ever single driver that doesnt give rendernodes
but so far seems only to be evdi.

problem that occured is a 3 gpu situation, the evdi card ended up using
a rendernode for a complete different gpu because it fallbacked to that.
2025-10-06 13:04:33 +02:00
655e067f96
version: bump to 0.9.5 2025-10-03 14:58:18 +01:00