Skip to content

feat(graphics): reported output changes to gfxfb's clients as events - #464

Merged
FlareCoding merged 1 commit into
pr/stlxdm-hw-cursorfrom
pr/gfxfb-output-events
Oct 26, 2026
Merged

FlareCoding merged 1 commit into
pr/stlxdm-hw-cursorfrom
pr/gfxfb-output-events

Conversation

@FlareCoding

@FlareCoding FlareCoding commented Oct 25, 2026 •

Copy link
Copy Markdown
Owner

Summary

gfxfb learns when an output (what shows one monitor's picture) lights, goes dark or relights at another mode, tells every open file of /dev/gfxfb through an output event (a record read returns naming the output), and moves the primary, the role of the output a one-screen program draws on, off an output that goes dark.

Changes

  • Let a display report an output's change: gfxfb::output_changed() reads the output again, records a lit output's base buffer (the buffer it was lit with, which offset 0 maps on the primary output) and queues a GFXFB_EVENT_OUTPUT event naming the output in every open file, and output_state.relighting marks an output taken dark to be lit again at another mode. A failed display's reports change nothing, and neither the boot display nor virtio-gpu reports a change.
  • Give each file at most one output event per output: queue_output_event() puts a newer output event at the tail of the file's queue in place of the one the file holds for that output, so the queue's 2 x GFXFB_OUTPUTS_MAX records always suffice and, since a display ends an output's present before reporting it dark, a file reads that present's GFXFB_PRESENT_DARK end before the output's event. The event wakes read and poll, and only an unread present event, never an output event, fails the file's next present on that output with EBUSY.
  • Keep a primary output that one screen can draw on: the primary stays on an output that relights, moves from an output that goes dark to the lowest output with a recorded base buffer, which gets an output event too, and with no primary output goes to the first output lit with one. While there is no primary output or it relights, GFXFB_GET_INFO and GFXFB_FLUSH fail with EAGAIN and mmap at offset 0 is refused, each reading the primary under the node's outputs lock.
  • Hand back what a dark output held: a dark output's base buffer and the buffer it showed go back to the display once no handle or mapping holds them, the stale mark a skipped flush leaves (which makes the base buffer's next present copy it whole) clears, and the output loses its cursor until the next picture, as gfxfb.h's display contract and gfxfb_abi.h's cursor paragraph state. A lit output keeps showing a buffer a program created, since its hardware still reads it.
  • Keep stlxdm's present ends apart from output events: flip_presenter::take_end() returns at an event that is not a present event, leaving end_fd() set, so an output event never reads as a present that latched.
  • Tests: on the fake display, an output event reaching every file behind the presenter's GFXFB_PRESENT_DARK end, a blocking read woken by a change, a close kept waiting through an output change, a queue holding a present event and an output event for each of 16 outputs, a replaced output event keeping a wrapped queue in order, the primary staying on a relighting output and moving off a dark one from output 1 to output 0 and back and to the lowest of several lit outputs, a lit output without a recorded base buffer counted as dark, a dark output's buffers handed back, a program's buffer shown before a lit report kept, a relit output's stale mark cleared and its cursor hidden, the stale mark kept through reports that keep the base buffer, a failed display's reports ignored, and reports for another display or a missing output dropped.
  • Boots: in QEMU on x86_64 and aarch64, against pr/stlxdm-hw-cursor, the desktop came up on virtio-gpu and on the firmware's framebuffer with no faults or forbidden log lines. No boot reports an output change, so the boots show only that the paths the base runs are unchanged.

Note

Medium Risk
Changes primary-output selection, buffer lifetime, and client event queues in the kernel graphics path; behavior is heavily tested but any future driver calling output_changed() must follow the new ordering and relighting contract.

Overview
Adds runtime hotplug-style output notifications for /dev/gfxfb: displays call new gfxfb::output_changed(), gfxfb re-reads the output, updates per-output base/shown buffer records, moves or retains the primary output (including relighting via output_state.relighting), and delivers GFXFB_EVENT_OUTPUT to every open client—replacing any prior output event for that output and waking read/poll.

Primary drawing path no longer uses a fixed m_primary_record; GFXFB_GET_INFO, GFXFB_FLUSH, and mmap offset 0 go through primary_base() and return EAGAIN while there is no primary or the primary is relighting. Present-event tracking is tightened so only GFXFB_EVENT_PRESENT blocks the next present on an output.

stlxdm ignores non-present events in take_end() so output events do not look like latched presents. virtio-gpu and boot display only set relighting = false (no reports yet). ABI/kernel docs and a large gfxfb test suite cover primary moves, buffer drops on dark, failed-display no-ops, and event ordering.

Reviewed by Cursor Bugbot for commit 08919d9. Bugbot is set up for automated code reviews on this repo. Configure here.

@FlareCoding
FlareCoding added this pull request to stack #465 October 25, 2026 22:03
A display could not report an output that lit or went dark, so programs
kept drawing to a primary output no monitor showed. Each change reaches
every client as an event, and the primary moves to a lit output.
@FlareCoding
FlareCoding force-pushed the pr/gfxfb-output-events branch from 08919d9 to 4d6b837 Compare October 25, 2026 23:18
@FlareCoding
FlareCoding merged commit 677c8c0 into master Oct 26, 2026
11 checks passed
@FlareCoding
FlareCoding deleted the pr/gfxfb-output-events branch October 26, 2026 03:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant