Skip to content

macos: refresh dpi_scale per Metal frame; guard backingScaleFactor=0#648

Merged
not-fl3 merged 1 commit into
not-fl3:masterfrom
benface:pr-macos-metal-highdpi
Jun 15, 2026
Merged

macos: refresh dpi_scale per Metal frame; guard backingScaleFactor=0#648
not-fl3 merged 1 commit into
not-fl3:masterfrom
benface:pr-macos-metal-highdpi

Conversation

@benface

@benface benface commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Two related fixes for macOS Metal high-DPI behaviour:

  1. Guard backingScaleFactor = 0. NSWindow.backingScaleFactor returns 0.0 when the window isn't yet attached to a screen — exactly the state during the startup update_dimensions() call (before makeKeyAndOrderFront). Upstream then stores dpi_scale = 0, and any downstream divide by dpi_scale (e.g. macroquad's screen_width()) either NaN's or pins the UI to 0×0. Now we skip the assignment when the value is non-positive, leaving the prior (correct) value in place until a later call catches a real scale.

  2. Refresh dpi_scale per Metal frame. OpenGL's draw_rect calls update_dimensions() every frame; the Metal draw_rect didn't, so even after the guarded startup case the initial dpi_scale was never refreshed. Retina apps using the Metal backend rendered at point resolution. This change adds the matching call to Metal's draw_rect.

Test plan

  • Retina MacBook (backingScaleFactor = 2): macOS Metal app now reports dpi_scale = 2.0 consistently from frame 1.
  • Resize + display-move: dpi_scale follows when the window is dragged between Retina and non-Retina displays.

@benface benface force-pushed the pr-macos-metal-highdpi branch from e70097d to dc7eed1 Compare June 14, 2026 05:52
NSWindow.backingScaleFactor returns 0.0 when the window isn't attached
to a screen yet — which is exactly the state during the startup
update_dimensions() call (before makeKeyAndOrderFront). Without this
guard the Metal backend silently records dpi_scale = 0, which then gets
divided by downstream (e.g. macroquad's screen_width()) and either
hangs at NaN or pins the UI at 0×0.

Two fixes here:
- update_dimensions() now skips the dpi_scale assignment when
  backingScaleFactor is 0, leaving the previous (correct) value in
  place until a later call catches a valid scale.
- Metal's draw_rect (the per-frame entry point) now calls
  update_dimensions(), matching the OpenGL path. Otherwise the
  initial dpi_scale never gets refreshed and Retina apps render at
  point resolution.
@benface benface force-pushed the pr-macos-metal-highdpi branch from dc7eed1 to 245dc58 Compare June 14, 2026 05:53
@not-fl3 not-fl3 merged commit 14c6fc3 into not-fl3:master Jun 15, 2026
11 checks passed
@benface benface deleted the pr-macos-metal-highdpi branch June 15, 2026 12: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.

2 participants