iOS and Android checked the backend setting, which a change sets right
away while the restart prompt is still up. A TV connected then got an
output OpenGL can't draw to, and showed black instead of mirroring.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The add request holds the layer unretained, and the swapchain only takes
a reference once it's handled. If the TV disconnected (or the setting
changed) before that, the window and the layer were freed with the add
still queued. The view controller now keeps a reference for the requests,
released after Native_RemoveOutputAndWait, off the main thread.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Graphics > "External display" on iOS and Android. "Show the game" (the
default) is the TV mode, "Mirror the screen" leaves the TV to the system.
A change applies right away. It's disabled on backends that can't draw to
a second swapchain.
On Android 12 and up, a second screen that's part of the device (like a
dual-screen handheld's) isn't used, so the game doesn't move there by
itself.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The SDL game window gets its Vulkan surface the same way the main window
does, so it should work on Linux too. Windows and OpenGL aren't done.
EmuScreen asks the draw context for the output's size, which follows a
recreated Vulkan swapchain.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The 1080p cap was meant to save Wi-Fi bandwidth, but an Apple TV 4K
only offers 3840x2160 over AirPlay, so the stream was 4K anyway, just
upscaled.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
An external display (like an Apple TV over AirPlay) becomes a Game
output, when the backend is Metal. The game is shown there full screen,
and the phone shows the touch controls with "Playing on TV" in place of
the game. The menus stay on the phone. With other backends, iOS keeps
mirroring.
Up to iOS 26 the external display scene comes from the Info.plist role.
iOS 27 ignores that, and only offers the scene to apps that register a
scene accessory for it, so we do that too. The registration is withdrawn
when the view controller shuts down, so it follows a backend change, and
a restart now goes to the app's scene rather than the first one.
An Apple TV 4K only offers 3840x2160 over AirPlay, so the stream stays
4K, but we render at 1920x1080 and let the layer scale it up.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>