Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ndk/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
- Improve library and structure documentation, linking back to the NDK docs more rigorously. (#290)
- **Breaking:** input_queue: `get_event()` now returns a `Result` with `std::io::Error`; `InputQueueError` has been removed. (#292)
- **Breaking:** input_queue: `has_events()` now returns a `bool` directly without being wrapped in `Result`. (#294)
- **Breaking:** hardware_buffer: `HardwareBufferError` has been removed and replaced with `std::io::Error` in return types. (#295)
- **Breaking:** Update `jni` crate (used in public API) from `0.18` to `0.19`. (#300)

# 0.6.0 (2022-01-05)
Expand Down
56 changes: 18 additions & 38 deletions ndk/src/hardware_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

#![cfg(feature = "hardware_buffer")]

use crate::utils::status_to_io_result;

pub use super::hardware_buffer_format::HardwareBufferFormat;
use jni_sys::{jobject, JNIEnv};
use std::{
convert::TryInto, mem::MaybeUninit, ops::Deref, os::raw::c_void, os::unix::io::RawFd,
ptr::NonNull,
convert::TryInto, 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 @@ -84,21 +86,12 @@ impl HardwareBufferUsage {
Self(ffi::AHardwareBuffer_UsageFlags_AHARDWAREBUFFER_USAGE_VENDOR_19);
}

#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
pub struct HardwareBufferError(pub i32);

pub type Result<T, E = HardwareBufferError> = std::result::Result<T, E>;

pub type Rect = ffi::ARect;

fn construct<T>(with_ptr: impl FnOnce(*mut T) -> i32) -> Result<T, HardwareBufferError> {
fn construct<T>(with_ptr: impl FnOnce(*mut T) -> i32) -> Result<T> {
let mut result = MaybeUninit::uninit();
let status = with_ptr(result.as_mut_ptr());
if status == 0 {
Ok(unsafe { result.assume_init() })
} else {
Err(HardwareBufferError(status))
}
status_to_io_result(status, unsafe { result.assume_init() })
}

/// A native [`AHardwareBuffer *`]
Expand Down Expand Up @@ -141,7 +134,7 @@ impl HardwareBuffer {
/// Create a [`HardwareBuffer`] from JNI pointers
///
/// # Safety
/// By calling this function, you assert that it these are valid pointers to JNI objects.
/// By calling this function, you assert that these are valid pointers to JNI objects.
pub unsafe fn from_jni(env: *mut JNIEnv, hardware_buffer: jobject) -> Self {
let ptr = ffi::AHardwareBuffer_fromHardwareBuffer(env, hardware_buffer);

Expand Down Expand Up @@ -219,17 +212,13 @@ impl HardwareBuffer {
bytes_per_stride.as_mut_ptr(),
)
};
if status == 0 {
Ok(unsafe {
LockedPlaneInfo {
virtual_address: virtual_address.assume_init(),
bytes_per_pixel: bytes_per_pixel.assume_init() as u32,
bytes_per_stride: bytes_per_stride.assume_init() as u32,
}
})
} else {
Err(HardwareBufferError(status))
}
status_to_io_result(status, ()).map(|()| unsafe {
LockedPlaneInfo {
virtual_address: virtual_address.assume_init(),
bytes_per_pixel: bytes_per_pixel.assume_init() as u32,
bytes_per_stride: bytes_per_stride.assume_init() as u32,
}
})
}

#[cfg(feature = "api-level-29")]
Expand All @@ -256,11 +245,7 @@ impl HardwareBuffer {

pub fn unlock(&self) -> Result<()> {
let status = unsafe { ffi::AHardwareBuffer_unlock(self.as_ptr(), std::ptr::null_mut()) };
if status == 0 {
Ok(())
} else {
Err(HardwareBufferError(status))
}
status_to_io_result(status, ())
}

/// Returns a fence file descriptor that will become signalled when unlocking is completed,
Expand All @@ -283,14 +268,9 @@ impl HardwareBuffer {
}

pub fn send_handle_to_unix_socket(&self, socket_fd: RawFd) -> Result<()> {
unsafe {
let status = ffi::AHardwareBuffer_sendHandleToUnixSocket(self.as_ptr(), socket_fd);
if status == 0 {
Ok(())
} else {
Err(HardwareBufferError(status))
}
}
let status =
unsafe { ffi::AHardwareBuffer_sendHandleToUnixSocket(self.as_ptr(), socket_fd) };
status_to_io_result(status, ())
}

pub fn acquire(&self) -> HardwareBufferRef {
Expand Down
15 changes: 7 additions & 8 deletions ndk/src/input_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
//!
//! [`AInputQueue`]: https://developer.android.com/ndk/reference/group/input#ainputqueue

use std::io::{Error, Result};
use std::io::Result;
use std::os::raw::c_int;
use std::ptr::{self, NonNull};

use crate::event::InputEvent;
#[cfg(doc)]
use crate::event::KeyEvent;
use crate::looper::ForeignLooper;
use crate::utils::status_to_io_result;

/// A native [`AInputQueue *`]
///
Expand Down Expand Up @@ -43,18 +44,16 @@ impl InputQueue {
/// Returns [`None`] if no event is available.
pub fn get_event(&self) -> Result<Option<InputEvent>> {
let mut out_event = ptr::null_mut();
match unsafe { ffi::AInputQueue_getEvent(self.ptr.as_ptr(), &mut out_event) } {
0 => {
let status = unsafe { ffi::AInputQueue_getEvent(self.ptr.as_ptr(), &mut out_event) };
match status_to_io_result(status, ()) {
Ok(()) => {
debug_assert!(!out_event.is_null());
Ok(Some(unsafe {
InputEvent::from_ptr(NonNull::new_unchecked(out_event))
}))
}
r if r < 0 => match Error::from_raw_os_error(-r) {
e if e.kind() == std::io::ErrorKind::WouldBlock => Ok(None),
e => Err(e),
},
r => unreachable!("AInputQueue_getEvent returned positive integer {}", r),
Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => Ok(None),
Err(e) => Err(e),
}
}

Expand Down
1 change: 1 addition & 0 deletions ndk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ pub mod native_activity;
pub mod native_window;
pub mod surface_texture;
pub mod trace;
mod utils;
14 changes: 6 additions & 8 deletions ndk/src/native_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
//!
//! [`ANativeWindow`]: https://developer.android.com/ndk/reference/group/a-native-window#anativewindow

use crate::utils::status_to_io_result;

pub use super::hardware_buffer_format::HardwareBufferFormat;
use jni_sys::{jobject, JNIEnv};
use raw_window_handle::{AndroidNdkHandle, HasRawWindowHandle, RawWindowHandle};
use std::{convert::TryFrom, ffi::c_void, ptr::NonNull};
use std::{convert::TryFrom, ffi::c_void, io::Result, ptr::NonNull};

// [`NativeWindow`] represents the producer end of an image queue
///
Expand Down Expand Up @@ -94,16 +96,12 @@ impl NativeWindow {
width: i32,
height: i32,
format: Option<HardwareBufferFormat>,
) -> Result<(), i32> {
) -> Result<()> {
let format: u32 = format.map_or(0, |f| f.into());
let r = unsafe {
let status = unsafe {
ffi::ANativeWindow_setBuffersGeometry(self.ptr.as_ptr(), width, height, format as i32)
};
if r == 0 {
Ok(())
} else {
Err(r)
}
status_to_io_result(status, ())
}

/// Return the [`NativeWindow`] associated with a JNI [`android.view.Surface`] pointer.
Expand Down
39 changes: 8 additions & 31 deletions ndk/src/surface_texture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,9 @@
//! [`ASurfaceTexture`]: https://developer.android.com/ndk/reference/group/surface-texture
#![cfg(feature = "api-level-28")]

use crate::native_window::NativeWindow;
use crate::{native_window::NativeWindow, utils::status_to_io_result};
use jni_sys::{jobject, JNIEnv};
use std::{
convert::TryInto,
io::{Error, Result},
ptr::NonNull,
time::Duration,
};
use std::{convert::TryInto, io::Result, ptr::NonNull, time::Duration};

/// An opaque type to manage [`android.graphics.SurfaceTexture`] from native code
///
Expand Down Expand Up @@ -88,14 +83,8 @@ impl SurfaceTexture {
/// contexts. Note, however, that the image contents are only accessible from one OpenGL ES
/// context at a time.
pub fn attach_to_gl_context(&self, tex_name: u32) -> Result<()> {
match unsafe { ffi::ASurfaceTexture_attachToGLContext(self.ptr.as_ptr(), tex_name) } {
0 => Ok(()),
r if r < 0 => Err(Error::from_raw_os_error(-r)),
r => unreachable!(
"ASurfaceTexture_attachToGLContext returned positive integer {}",
r
),
}
let status = unsafe { ffi::ASurfaceTexture_attachToGLContext(self.ptr.as_ptr(), tex_name) };
status_to_io_result(status, ())
}

/// Detach the [`SurfaceTexture`] from the OpenGL ES context that owns the OpenGL ES texture
Expand All @@ -110,14 +99,8 @@ impl SurfaceTexture {
/// contexts. Note, however, that the image contents are only accessible from one OpenGL ES
/// context at a time.
pub fn detach_from_gl_context(&self) -> Result<()> {
match unsafe { ffi::ASurfaceTexture_detachFromGLContext(self.ptr.as_ptr()) } {
0 => Ok(()),
r if r < 0 => Err(Error::from_raw_os_error(-r)),
r => unreachable!(
"ASurfaceTexture_detachFromGLContext returned positive integer {}",
r
),
}
let status = unsafe { ffi::ASurfaceTexture_detachFromGLContext(self.ptr.as_ptr()) };
status_to_io_result(status, ())
}

/// Retrieve the 4x4 texture coordinate transform matrix associated with the texture image set
Expand Down Expand Up @@ -170,13 +153,7 @@ impl SurfaceTexture {
/// calling thread. It will implicitly bind its texture to the `GL_TEXTURE_EXTERNAL_OES`
/// texture target.
pub fn update_tex_image(&self) -> Result<()> {
match unsafe { ffi::ASurfaceTexture_updateTexImage(self.ptr.as_ptr()) } {
0 => Ok(()),
r if r < 0 => Err(Error::from_raw_os_error(-r)),
r => unreachable!(
"ASurfaceTexture_updateTexImage returned positive integer {}",
r
),
}
let status = unsafe { ffi::ASurfaceTexture_updateTexImage(self.ptr.as_ptr()) };
status_to_io_result(status, ())
}
}
14 changes: 14 additions & 0 deletions ndk/src/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//! Internal utilities
use std::io::{Error, Result};

/// Turns standard `<errno.h>` status codes - typically rewrapped by Android's [`Errors.h`] - into
/// Rust's [`std::io::Error`].
///
/// [`Errors.h`]: https://cs.android.com/android/platform/superproject/+/master:system/core/libutils/include/utils/Errors.h
pub(crate) fn status_to_io_result<T>(status: i32, value: T) -> Result<T> {
match status {
0 => Ok(value),
r if r < 0 => Err(Error::from_raw_os_error(-r)),
r => unreachable!("Status is positive integer {}", r),
}
}