Repository navigation
feat(graphics): reported virtio-gpu's scanout changes to gfxfb - #466
Merged
Merged
Conversation
virtio-gpu lit one scanout at attach and never followed the device's changes, so a resized scanout kept its old mode and an added one stayed blank. A resized scanout is lit again with a new base buffer.
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.
Summary
virtio-gpu lights every scanout (one of the device's virtual monitors) the device enables and follows the device's changes to them, reporting each change to gfxfb (the kernel's display interface), which queues an output event (a record naming the changed output) for every open file of /dev/gfxfb.
Changes
attach()routes the device's configuration change interrupt to an MSI-X vector of its own, whose handler wakes the driver's task, and the task clears the display event (the bit of the device's config region that marks a change of the scanouts) before reading the scanouts with GET_DISPLAY_INFO, so a change the read misses raises the interrupt again. A device without that vector keeps its scanouts as attach lit them, with a warning in the boot log.update_scanout()lights a dark scanout the device enables at a usable size (nonzero and at most 4096 by 4096), takes a lit one dark when the device disables it or reports an unusable size, and takes a resized one dark withrelighting(gfxfb's mark of an output being lit again at another mode) set before lighting it at its new size, callinggfxfb::output_changed()after each change with no lock held. At attach,light_enabled_scanouts()lights every scanout the device enables at a usable size, or scanout 0 at 1024x768 when there is none.allocate_base()allocates a new base buffer (the buffer a scanout is lit with, which userland draws into) for every lighting, with no lock held and before a relight takes the scanout dark, and once gfxfb hands it back, after the scanout goes dark and no handle or mapping holds it, the driver's task destroys it as it destroys a buffer fromcreate_buffer().flush()clips each rect to the scanout's current base buffer, since a relight may have replaced the one whose regions gfxfb named.darken_scanout()hides the scanout's cursor when shown and sends SET_SCANOUT naming no resource, and only once the device confirms each command it sent does it end the scanout's unended present, if any, with GFXFB_PRESENT_DARK and cancel its latch timer. A darkening the device refuses keeps the scanout lit and reports nothing, and a relight that fails reports the scanout dark withoutrelighting, each waiting for the device's next change to try again, except after a command has gone unanswered, when every later read of the scanouts fails.virtio_gpu_scanoutholds each scanout's base buffer, latch timer, shown resource and cursor, so presents, latch reports, both cursor calls,flush(),read_output()andbase_buffer()act on the scanout they name. One spinlock covers every scanout's base, relighting mark and latch, soread_output(),base_buffer()and the latch timer never wait behind a command batch.relightingand "failed to read the scanouts after a configuration change" are checked by reading. Every boot's device enabled scanout 0 at a usable size and no attach failed after lighting a scanout, so the fallback scanout's first change, a scanout reported past 4096 pixels, anddetach()freeing an unregistered display's base buffers or a base buffer the device may still read are checked by reading too.GFXFB_FLUSHreaches the driver only for gfxfb's primary output (the output a one-screen program draws on), output 0 in every boot, with each rect already clipped to that output's base buffer, soflush()on another scanout andflush()'s own clip, which changes a rect only when a relight lands between gfxfb's clip and the call, are checked by reading.Note
High Risk
Large kernel graphics driver change affecting DMA buffer lifetime, IRQ/task locking, and present/latch semantics across multiple outputs; incorrect teardown or relight could leak GPU memory or confuse userland display state.
Overview
Multi-scanout virtio-gpu replaces the single lit scanout and shared
m_base_bufferwith per-outputvirtio_gpu_scanoutstate (base buffer, cursor, latch timer, present tracking). Attach lights every device-enabled usable mode vialight_enabled_scanouts(), with a 1024×768 fallback on scanout 0 when none are usable.Runtime hotplug uses a dedicated MSI-X config vector (
CONFIG_VECTOR):on_interruptwakes the driver task, which clearsVIRTIO_GPU_EVENT_DISPLAY, re-reads display info, and runsupdate_scanout()per output—darkening (cursor hide, emptySET_SCANOUT,GFXFB_PRESENT_DARK), relighting at new sizes withgfxfb::output_changed(), and clippingflush()rects to the current base. Without config MSI-X, scanouts stay as at attach (warned in the log).Supporting changes:
read_display_info()instead of picking one scanout;ERR_RAM_HELD/m_held_basefor leaked backing after failed light;m_scanout_lockfor non-blockingread_output()/base_buffer(); work queue merges config changes with buffer releases.Reviewed by Cursor Bugbot for commit 528acb9. Bugbot is set up for automated code reviews on this repo. Configure here.