Skip to content

Commit

Permalink
hardware_buffer_format: Add catch-all variant
Browse files Browse the repository at this point in the history
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()`.
  • Loading branch information
spencercw committed Jul 25, 2023
1 parent b520751 commit 382c717
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 28 deletions.
1 change: 1 addition & 0 deletions ndk/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
8 changes: 4 additions & 4 deletions ndk/src/hardware_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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,
}
Expand Down Expand Up @@ -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,
Expand Down
116 changes: 97 additions & 19 deletions ndk/src/hardware_buffer_format.rs
Original file line number Diff line number Diff line change
@@ -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<ffi::AHardwareBuffer_Format> 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<HardwareBufferFormat> 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 {
Expand Down Expand Up @@ -75,6 +152,7 @@ impl HardwareBufferFormat {
Self::YCbCr_P010 => return None,
#[cfg(feature = "api-level-26")]
Self::R8_UNORM => 1,
Self::Unknown(_) => return None,
})
}
}
4 changes: 2 additions & 2 deletions ndk/src/native_activity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
7 changes: 4 additions & 3 deletions ndk/src/native_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -99,7 +99,8 @@ impl NativeWindow {
height: i32,
format: Option<HardwareBufferFormat>,
) -> Result<()> {
let format: u32 = format.map_or(0, |f| f.into());
let format: Option<ffi::AHardwareBuffer_Format> = 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)
};
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit 382c717

Please sign in to comment.