From 04482d5a2ee9783a70a0e94dfbf5b7bf0b9e0857 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Fri, 23 May 2025 16:07:09 +0200 Subject: [PATCH] fix: Allow unknown bit-depth on macOS (#4190) It is unclear what values CGDisplayModeCopyPixelEncoding is allowed to return, so let's make sure to handle unknown cases. --- src/changelog/unreleased.md | 1 + src/platform_impl/apple/appkit/ffi.rs | 2 +- src/platform_impl/apple/appkit/monitor.rs | 14 +++++++++----- winit-core/src/monitor.rs | 7 +++++++ 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/changelog/unreleased.md b/src/changelog/unreleased.md index 67ea9349..741f92ef 100644 --- a/src/changelog/unreleased.md +++ b/src/changelog/unreleased.md @@ -248,3 +248,4 @@ changelog entry. - On macOS, fixed the scancode conversion for audio volume keys. - On macOS, fixed the scancode conversion for `IntlBackslash`. - On macOS, fixed redundant `SurfaceResized` event at window creation. +- On macOS, don't panic on monitors with unknown bit-depths. diff --git a/src/platform_impl/apple/appkit/ffi.rs b/src/platform_impl/apple/appkit/ffi.rs index a42be14a..0a07499b 100644 --- a/src/platform_impl/apple/appkit/ffi.rs +++ b/src/platform_impl/apple/appkit/ffi.rs @@ -11,8 +11,8 @@ use objc2_core_graphics::CGDirectDisplayID; pub const IO16BitDirectPixels: &str = "-RRRRRGGGGGBBBBB"; pub const IO32BitDirectPixels: &str = "--------RRRRRRRRGGGGGGGGBBBBBBBB"; - pub const kIO30BitDirectPixels: &str = "--RRRRRRRRRRGGGGGGGGGGBBBBBBBBBB"; +pub const kIO64BitDirectPixels: &str = "-16R16G16B16"; // `CGDisplayCreateUUIDFromDisplayID` comes from the `ColorSync` framework. // However, that framework was only introduced "publicly" in macOS 10.13. diff --git a/src/platform_impl/apple/appkit/monitor.rs b/src/platform_impl/apple/appkit/monitor.rs index a84462be..846ed15d 100644 --- a/src/platform_impl/apple/appkit/monitor.rs +++ b/src/platform_impl/apple/appkit/monitor.rs @@ -66,17 +66,21 @@ impl VideoModeHandle { refresh_rate_millihertz: Option, ) -> Self { unsafe { + // The bit-depth is basically always 32 since macOS 10.12. #[allow(deprecated)] let pixel_encoding = CGDisplayMode::pixel_encoding(Some(&native_mode.0)).unwrap().to_string(); let bit_depth = if pixel_encoding.eq_ignore_ascii_case(ffi::IO32BitDirectPixels) { - 32 + NonZeroU16::new(32) } else if pixel_encoding.eq_ignore_ascii_case(ffi::IO16BitDirectPixels) { - 16 + NonZeroU16::new(16) } else if pixel_encoding.eq_ignore_ascii_case(ffi::kIO30BitDirectPixels) { - 30 + NonZeroU16::new(30) + } else if pixel_encoding.eq_ignore_ascii_case(ffi::kIO64BitDirectPixels) { + NonZeroU16::new(64) } else { - unimplemented!() + warn!(?pixel_encoding, "unknown bit depth"); + None }; let mode = VideoMode::new( @@ -84,7 +88,7 @@ impl VideoModeHandle { CGDisplayMode::pixel_width(Some(&native_mode.0)) as u32, CGDisplayMode::pixel_height(Some(&native_mode.0)) as u32, ), - NonZeroU16::new(bit_depth), + bit_depth, refresh_rate_millihertz, ); diff --git a/winit-core/src/monitor.rs b/winit-core/src/monitor.rs index 6fff6c94..f24e3888 100644 --- a/winit-core/src/monitor.rs +++ b/winit-core/src/monitor.rs @@ -151,6 +151,13 @@ impl VideoMode { /// Returns the bit depth of this video mode, as in how many bits you have /// available per color. This is generally 24 bits or 32 bits on modern /// systems, depending on whether the alpha channel is counted or not. + /// + /// # Platform-specific + /// + /// - **macOS**: Video modes do not control the bit depth of the monitor, so this often defaults + /// to 32. + /// - **iOS**: Always returns `None`. + /// - **Wayland**: Always returns `None`. pub fn bit_depth(&self) -> Option { self.bit_depth }