From 382c717d83dca62cdb0fc865b06eb97dbbfb542f Mon Sep 17 00:00:00 2001 From: Chris Spencer Date: Wed, 5 Jul 2023 11:44:08 +0100 Subject: [PATCH] hardware_buffer_format: Add catch-all variant Hardware buffers can have private formats which don't appear in the NDK header. Add a catch-all variant to avoid panicking in `HardwareBuffer::describe()`. --- ndk/CHANGELOG.md | 1 + ndk/src/hardware_buffer.rs | 8 +-- ndk/src/hardware_buffer_format.rs | 116 +++++++++++++++++++++++++----- ndk/src/native_activity.rs | 4 +- ndk/src/native_window.rs | 7 +- 5 files changed, 108 insertions(+), 28 deletions(-) diff --git a/ndk/CHANGELOG.md b/ndk/CHANGELOG.md index ed244f69..c9365002 100644 --- a/ndk/CHANGELOG.md +++ b/ndk/CHANGELOG.md @@ -13,6 +13,7 @@ - **Breaking:** media_codec: Return `MaybeUninit` bytes in `buffer_mut()`. (#403) - native_window: Add `lock()` to blit raw pixel data. (#404) - hardware_buffer_format: Add `YCbCr_P010` and `R8_UNORM` variants. (#405) +- hardware_buffer_format: Add catch-all variant. (#407) # 0.7.0 (2022-07-24) diff --git a/ndk/src/hardware_buffer.rs b/ndk/src/hardware_buffer.rs index db8c29ec..e6de8f69 100644 --- a/ndk/src/hardware_buffer.rs +++ b/ndk/src/hardware_buffer.rs @@ -9,8 +9,7 @@ use crate::utils::status_to_io_result; pub use super::hardware_buffer_format::HardwareBufferFormat; use jni_sys::{jobject, JNIEnv}; use std::{ - convert::TryInto, io::Result, mem::MaybeUninit, ops::Deref, os::raw::c_void, - os::unix::io::RawFd, ptr::NonNull, + io::Result, mem::MaybeUninit, ops::Deref, os::raw::c_void, os::unix::io::RawFd, ptr::NonNull, }; #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -204,7 +203,7 @@ impl HardwareBuffer { width: desc.width, height: desc.height, layers: desc.layers, - format: desc.format.try_into().unwrap(), + format: ffi::AHardwareBuffer_Format(desc.format).into(), usage: HardwareBufferUsage(ffi::AHardwareBuffer_UsageFlags(desc.usage)), stride: desc.stride, } @@ -473,11 +472,12 @@ pub struct HardwareBufferDesc { impl HardwareBufferDesc { fn into_native(self) -> ffi::AHardwareBuffer_Desc { + let format: ffi::AHardwareBuffer_Format = self.format.into(); ffi::AHardwareBuffer_Desc { width: self.width, height: self.height, layers: self.layers, - format: self.format.try_into().unwrap(), + format: format.0, usage: self.usage.0 .0, stride: self.stride, rfu0: 0, diff --git a/ndk/src/hardware_buffer_format.rs b/ndk/src/hardware_buffer_format.rs index 7095099a..ac95effd 100644 --- a/ndk/src/hardware_buffer_format.rs +++ b/ndk/src/hardware_buffer_format.rs @@ -1,45 +1,122 @@ //! Bindings for [`AHardwareBuffer_Format`] //! //! [`AHardwareBuffer_Format`]: https://developer.android.com/ndk/reference/group/a-hardware-buffer#ahardwarebuffer_format -use num_enum::{IntoPrimitive, TryFromPrimitive}; /// Buffer pixel formats. -#[repr(u32)] -#[derive(Copy, Clone, Debug, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[allow(non_camel_case_types)] pub enum HardwareBufferFormat { /// Matches deprecated [`ffi::ANativeWindow_LegacyFormat::WINDOW_FORMAT_RGBA_8888`]. - R8G8B8A8_UNORM = ffi::AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM.0, + R8G8B8A8_UNORM, /// Matches deprecated [`ffi::ANativeWindow_LegacyFormat::WINDOW_FORMAT_RGBX_8888`]. - R8G8B8X8_UNORM = ffi::AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM.0, + R8G8B8X8_UNORM, #[cfg(feature = "api-level-26")] - R8G8B8_UNORM = ffi::AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM.0, + R8G8B8_UNORM, /// Matches deprecated [`ffi::ANativeWindow_LegacyFormat::WINDOW_FORMAT_RGB_565`]. - R5G6B5_UNORM = ffi::AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM.0, + R5G6B5_UNORM, #[cfg(feature = "api-level-26")] - R16G16B16A16_FLOAT = ffi::AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT.0, + R16G16B16A16_FLOAT, #[cfg(feature = "api-level-26")] - R10G10B10A2_UNORM = ffi::AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM.0, + R10G10B10A2_UNORM, #[cfg(feature = "api-level-26")] - BLOB = ffi::AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_BLOB.0, + BLOB, #[cfg(feature = "api-level-26")] - D16_UNORM = ffi::AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_D16_UNORM.0, + D16_UNORM, #[cfg(feature = "api-level-26")] - D24_UNORM = ffi::AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_D24_UNORM.0, + D24_UNORM, #[cfg(feature = "api-level-26")] - D24_UNORM_S8_UINT = ffi::AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT.0, + D24_UNORM_S8_UINT, #[cfg(feature = "api-level-26")] - D32_FLOAT = ffi::AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_D32_FLOAT.0, + D32_FLOAT, #[cfg(feature = "api-level-26")] - D32_FLOAT_S8_UINT = ffi::AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT.0, + D32_FLOAT_S8_UINT, #[cfg(feature = "api-level-26")] - S8_UINT = ffi::AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_S8_UINT.0, + S8_UINT, #[cfg(feature = "api-level-26")] - Y8Cb8Cr8_420 = ffi::AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420.0, + Y8Cb8Cr8_420, #[cfg(feature = "api-level-26")] - YCbCr_P010 = ffi::AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_YCbCr_P010.0, + YCbCr_P010, #[cfg(feature = "api-level-26")] - R8_UNORM = ffi::AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8_UNORM.0, + R8_UNORM, + Unknown(ffi::AHardwareBuffer_Format), +} + +impl From for HardwareBufferFormat { + fn from(value: ffi::AHardwareBuffer_Format) -> Self { + use ffi::AHardwareBuffer_Format as AFormat; + use HardwareBufferFormat::*; + match value { + AFormat::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM => R8G8B8A8_UNORM, + AFormat::AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM => R8G8B8X8_UNORM, + #[cfg(feature = "api-level-26")] + AFormat::AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM => R8G8B8_UNORM, + AFormat::AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM => R5G6B5_UNORM, + #[cfg(feature = "api-level-26")] + AFormat::AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT => R16G16B16A16_FLOAT, + #[cfg(feature = "api-level-26")] + AFormat::AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM => R10G10B10A2_UNORM, + #[cfg(feature = "api-level-26")] + AFormat::AHARDWAREBUFFER_FORMAT_BLOB => BLOB, + #[cfg(feature = "api-level-26")] + AFormat::AHARDWAREBUFFER_FORMAT_D16_UNORM => D16_UNORM, + #[cfg(feature = "api-level-26")] + AFormat::AHARDWAREBUFFER_FORMAT_D24_UNORM => D24_UNORM, + #[cfg(feature = "api-level-26")] + AFormat::AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT => D24_UNORM_S8_UINT, + #[cfg(feature = "api-level-26")] + AFormat::AHARDWAREBUFFER_FORMAT_D32_FLOAT => D32_FLOAT, + #[cfg(feature = "api-level-26")] + AFormat::AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT => D32_FLOAT_S8_UINT, + #[cfg(feature = "api-level-26")] + AFormat::AHARDWAREBUFFER_FORMAT_S8_UINT => S8_UINT, + #[cfg(feature = "api-level-26")] + AFormat::AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 => Y8Cb8Cr8_420, + #[cfg(feature = "api-level-26")] + AFormat::AHARDWAREBUFFER_FORMAT_YCbCr_P010 => YCbCr_P010, + #[cfg(feature = "api-level-26")] + AFormat::AHARDWAREBUFFER_FORMAT_R8_UNORM => R8_UNORM, + _ => Unknown(value), + } + } +} + +impl From for ffi::AHardwareBuffer_Format { + fn from(value: HardwareBufferFormat) -> Self { + use ffi::AHardwareBuffer_Format as AFormat; + use HardwareBufferFormat::*; + match value { + R8G8B8A8_UNORM => AFormat::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, + R8G8B8X8_UNORM => AFormat::AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM, + #[cfg(feature = "api-level-26")] + R8G8B8_UNORM => AFormat::AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM, + R5G6B5_UNORM => AFormat::AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM, + #[cfg(feature = "api-level-26")] + R16G16B16A16_FLOAT => AFormat::AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT, + #[cfg(feature = "api-level-26")] + R10G10B10A2_UNORM => AFormat::AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM, + #[cfg(feature = "api-level-26")] + BLOB => AFormat::AHARDWAREBUFFER_FORMAT_BLOB, + #[cfg(feature = "api-level-26")] + D16_UNORM => AFormat::AHARDWAREBUFFER_FORMAT_D16_UNORM, + #[cfg(feature = "api-level-26")] + D24_UNORM => AFormat::AHARDWAREBUFFER_FORMAT_D24_UNORM, + #[cfg(feature = "api-level-26")] + D24_UNORM_S8_UINT => AFormat::AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT, + #[cfg(feature = "api-level-26")] + D32_FLOAT => AFormat::AHARDWAREBUFFER_FORMAT_D32_FLOAT, + #[cfg(feature = "api-level-26")] + D32_FLOAT_S8_UINT => AFormat::AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT, + #[cfg(feature = "api-level-26")] + S8_UINT => AFormat::AHARDWAREBUFFER_FORMAT_S8_UINT, + #[cfg(feature = "api-level-26")] + Y8Cb8Cr8_420 => AFormat::AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, + #[cfg(feature = "api-level-26")] + YCbCr_P010 => AFormat::AHARDWAREBUFFER_FORMAT_YCbCr_P010, + #[cfg(feature = "api-level-26")] + R8_UNORM => AFormat::AHARDWAREBUFFER_FORMAT_R8_UNORM, + Unknown(x) => x, + } + } } impl HardwareBufferFormat { @@ -75,6 +152,7 @@ impl HardwareBufferFormat { Self::YCbCr_P010 => return None, #[cfg(feature = "api-level-26")] Self::R8_UNORM => 1, + Self::Unknown(_) => return None, }) } } diff --git a/ndk/src/native_activity.rs b/ndk/src/native_activity.rs index 3f5fef3a..eb449cc1 100644 --- a/ndk/src/native_activity.rs +++ b/ndk/src/native_activity.rs @@ -216,8 +216,8 @@ impl NativeActivity { /// /// [`getWindow().setFormat()`]: https://developer.android.com/reference/android/view/Window#setFormat(int) pub fn set_window_format(&self, format: HardwareBufferFormat) { - let format: u32 = format.into(); - unsafe { ffi::ANativeActivity_setWindowFormat(self.ptr.as_ptr(), format as i32) } + let format: ffi::AHardwareBuffer_Format = format.into(); + unsafe { ffi::ANativeActivity_setWindowFormat(self.ptr.as_ptr(), format.0 as i32) } } /// Change the window flags of the given activity. diff --git a/ndk/src/native_window.rs b/ndk/src/native_window.rs index 5408acdc..969999e2 100644 --- a/ndk/src/native_window.rs +++ b/ndk/src/native_window.rs @@ -81,7 +81,7 @@ impl NativeWindow { pub fn format(&self) -> HardwareBufferFormat { let value = unsafe { ffi::ANativeWindow_getFormat(self.ptr.as_ptr()) }; let value = u32::try_from(value).unwrap(); - HardwareBufferFormat::try_from(value).unwrap() + HardwareBufferFormat::from(ffi::AHardwareBuffer_Format(value)) } /// Change the format and size of the window buffers. @@ -99,7 +99,8 @@ impl NativeWindow { height: i32, format: Option, ) -> Result<()> { - let format: u32 = format.map_or(0, |f| f.into()); + let format: Option = format.map(|f| f.into()); + let format: u32 = format.map_or(0, |f| f.0); let status = unsafe { ffi::ANativeWindow_setBuffersGeometry(self.ptr.as_ptr(), width, height, format as i32) }; @@ -179,7 +180,7 @@ impl<'a> NativeWindowBufferLockGuard<'a> { /// The format of the buffer. One of [`HardwareBufferFormat`]. pub fn format(&self) -> HardwareBufferFormat { let format = u32::try_from(self.buffer.format).unwrap(); - HardwareBufferFormat::try_from(format).unwrap() + HardwareBufferFormat::from(ffi::AHardwareBuffer_Format(format)) } /// The actual bits.