Skip to content

qemu: tell the guest the host display's refresh rate - #7982

Open
dragoshont wants to merge 1 commit into
utmapp:mainfrom
dragoshont:qemu/host-refresh-rate
Open

dragoshont wants to merge 1 commit into
utmapp:mainfrom
dragoshont:qemu/host-refresh-rate

Conversation

@dragoshont

@dragoshont dragoshont commented Oct 18, 2026 •

Copy link
Copy Markdown

Guests in UTM always get a 75 Hz display, whatever the Mac's display runs at.

QEMU only puts the host refresh rate in the guest's EDID when the display frontend reports it, and SPICE can't, so the guest gets a made-up 75 Hz mode. Windows 11 ARM64 on viogpu3d then lists only 75 Hz modes:

  • On a 60 Hz display about one frame in five is rendered and never shown. Hollow Knight: 70 fps in the guest, 57 reaching the window.
  • On a 120 Hz display the guest can't go above 75.

This passes the main screen's refresh rate to virtio GPU devices through QEMU's new refresh_rate property.

Depends on utmapp/qemu#7; without it QEMU rejects the argument. Related: #7820.

Testing: macOS 27.0.1, MacBook Pro M5 Max, external 60 Hz display plus the built-in 120 Hz panel. Debug build with utmapp/qemu#7, disposable Alpine VM with virtio-gpu-gl-pci:

VM started on QEMU argument Guest EDID
60 Hz display refresh_rate=60000 60.00 Hz
120 Hz display refresh_rate=120000 119.99 Hz
(current release) none 75.00 Hz

Windows 11 Pro ARM64 (build 26300, viogpu3d 100.6.101.58000, D3DMetal) on the same build:

VM started on Windows display modes
60 Hz display 60 Hz only
120 Hz display 120 Hz only, desktop composed at 120 Hz
(current release) 75 Hz only

The rate comes from NSScreen.main, the screen with the key window when the VM starts. Moving the window to another display later doesn't change it until the next start.

Test setup: an ad-hoc signed build has no app group, so UTM sets no APP_SANDBOX_GROUP_ID, Neptune can't create shared memory and Windows shows "Display output is not active". For these runs I set the group by hand; release builds aren't affected.

An AI agent ran these tests on my Mac.

I have read the AI contribution guidelines and have followed them to the best of my ability.

The guest learns its refresh rate from the EDID that QEMU generates. QEMU
only fills in the host rate when the GTK or Cocoa display reports it; SPICE
has no field for it, so with UTM every guest gets a made-up 75 Hz mode.
Windows then lists only 75 Hz modes and composes at 75 Hz, so on a 60 Hz
display about one frame in five is rendered and never shown, and a 120 Hz
display cannot be used at all.

Pass the main screen's refresh rate to virtio GPU devices with the new
refresh_rate property, which QEMU uses when the display reports none.

Assisted-by: GitHub Copilot:claude-opus-5.5
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