Skip to content

Commit

Permalink
ndk/native_window: Add lock() to blit raw pixel data
Browse files Browse the repository at this point in the history
  • Loading branch information
MarijnS95 committed Jun 16, 2023
1 parent a92cca4 commit 5d5e25a
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 6 deletions.
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@
> ndk-build | https://github.com/rust-mobile/cargo-apk |
> cargo-apk | https://github.com/rust-mobile/cargo-apk |
[![Rust](https://github.com/rust-mobile/ndk/workflows/Rust/badge.svg)](https://github.com/rust-mobile/ndk/actions) ![MIT license](https://img.shields.io/badge/License-MIT-green.svg) ![APACHE2 license](https://img.shields.io/badge/License-APACHE2-green.svg)
[![ci](https://github.com/rust-mobile/ndk/actions/workflows/rust.yml/badge.svg)](https://github.com/rust-mobile/ndk/actions/workflows/rust.yml) ![MIT license](https://img.shields.io/badge/License-MIT-green.svg) ![APACHE2 license](https://img.shields.io/badge/License-APACHE2-green.svg)

Rust bindings to the [Android NDK](https://developer.android.com/ndk)

Name | Description | Badges
--- | --- | ---
[`ndk-sys`](./ndk-sys) | Raw FFI bindings to the NDK | [![crates.io](https://img.shields.io/crates/v/ndk-sys.svg)](https://crates.io/crates/ndk-sys) [![crates.io](https://docs.rs/ndk-sys/badge.svg)](https://docs.rs/ndk-sys) [![MSRV](https://img.shields.io/badge/rustc-1.60.0+-ab6000.svg)](https://blog.rust-lang.org/2022/04/07/Rust-1.60.0.html)
[`ndk`](./ndk) | Safe abstraction of the bindings | [![crates.io](https://img.shields.io/crates/v/ndk.svg)](https://crates.io/crates/ndk) [![crates.io](https://docs.rs/ndk/badge.svg)](https://docs.rs/ndk) [![MSRV](https://img.shields.io/badge/rustc-1.64.0+-ab6000.svg)](https://blog.rust-lang.org/2022/09/22/Rust-1.64.0.html)

[`ndk-sys`](./ndk-sys) | Raw FFI bindings to the NDK | [![crates.io](https://img.shields.io/crates/v/ndk-sys.svg)](https://crates.io/crates/ndk-sys) [![Docs](https://docs.rs/ndk-sys/badge.svg)](https://docs.rs/ndk-sys) [![MSRV](https://img.shields.io/badge/rustc-1.60.0+-ab6000.svg)](https://blog.rust-lang.org/2022/04/07/Rust-1.60.0.html)
[`ndk`](./ndk) | Safe abstraction of the bindings | [![crates.io](https://img.shields.io/crates/v/ndk.svg)](https://crates.io/crates/ndk) [![Docs](https://docs.rs/ndk/badge.svg)](https://docs.rs/ndk) [![MSRV](https://img.shields.io/badge/rustc-1.64.0+-ab6000.svg)](https://blog.rust-lang.org/2022/09/22/Rust-1.64.0.html)

See these [`ndk-examples`](https://github.com/rust-mobile/cargo-apk/tree/main/examples/examples) and these [`rust-android-examples`](https://github.com/rust-mobile/rust-android-examples) for examples using the NDK.
1 change: 1 addition & 0 deletions ndk/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- **Breaking:** Renamed and moved "`media`" error types and helpers to a new `media_error` module. (#399)
- **Breaking:** media_codec: Wrap common dequeued-buffer status codes in enum. (#401)
- **Breaking:** media_codec: Return `MaybeUninit` bytes in `buffer_mut()`. (#403)
- native_window: Add `lock()` to blit raw pixel data. (#404)

# 0.7.0 (2022-07-24)

Expand Down
32 changes: 32 additions & 0 deletions ndk/src/hardware_buffer_format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub enum HardwareBufferFormat {
R8G8B8_UNORM = ffi::AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM.0,
/// Matches deprecated [`ffi::ANativeWindow_LegacyFormat::WINDOW_FORMAT_RGB_565`].
R5G6B5_UNORM = ffi::AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM.0,
#[cfg(feature = "api-level-26")]
R16G16B16A16_FLOAT = ffi::AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT.0,
#[cfg(feature = "api-level-26")]
R10G10B10A2_UNORM = ffi::AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM.0,
Expand All @@ -36,3 +37,34 @@ pub enum HardwareBufferFormat {
#[cfg(feature = "api-level-26")]
Y8Cb8Cr8_420 = ffi::AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420.0,
}

impl HardwareBufferFormat {
pub fn bytes_per_pixel(self) -> usize {
match self {
Self::R8G8B8A8_UNORM | Self::R8G8B8X8_UNORM => 4,
#[cfg(feature = "api-level-26")]
Self::R8G8B8_UNORM => 3,
Self::R5G6B5_UNORM => 2,
#[cfg(feature = "api-level-26")]
Self::R16G16B16A16_FLOAT => 8,
#[cfg(feature = "api-level-26")]
Self::R10G10B10A2_UNORM => 4,
#[cfg(feature = "api-level-26")]
Self::BLOB => 1,
#[cfg(feature = "api-level-26")]
Self::D16_UNORM => 2,
#[cfg(feature = "api-level-26")]
Self::D24_UNORM => 3,
#[cfg(feature = "api-level-26")]
Self::D24_UNORM_S8_UINT => 4,
#[cfg(feature = "api-level-26")]
Self::D32_FLOAT => 4,
#[cfg(feature = "api-level-26")]
Self::D32_FLOAT_S8_UINT => 5,
#[cfg(feature = "api-level-26")]
Self::S8_UINT => 1,
#[cfg(feature = "api-level-26")]
Self::Y8Cb8Cr8_420 => 3,
}
}
}
4 changes: 2 additions & 2 deletions ndk/src/native_activity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@ unsafe impl Send for NativeActivity {}
unsafe impl Sync for NativeActivity {}

impl NativeActivity {
/// Create a `NativeActivity` from a pointer
/// Create a [`NativeActivity`] from a pointer
///
/// # Safety
/// By calling this function, you assert that it is a valid pointer to a native
/// `ANativeActivity`.
/// [`ffi::ANativeActivity`].
pub unsafe fn from_ptr(ptr: NonNull<ffi::ANativeActivity>) -> Self {
Self { ptr }
}
Expand Down
57 changes: 57 additions & 0 deletions ndk/src/native_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,61 @@ impl NativeWindow {
pub unsafe fn to_surface(&self, env: *mut JNIEnv) -> jobject {
ffi::ANativeWindow_toSurface(env, self.ptr().as_ptr())
}

/// Lock the window's next drawing surface for writing.
///
/// Optionally pass the region you intend to draw into `dirty_bounds`. When this function
/// returns it is updated (commonly enlarged) with the actual area the caller needs to redraw.
pub fn lock(
&self,
dirty_bounds: Option<&mut ffi::ARect>,
) -> Result<NativeWindowBufferLockGuard> {
let dirty_bounds = match dirty_bounds {
Some(dirty_bounds) => dirty_bounds,
None => std::ptr::null_mut(),
};
let mut out = unsafe { std::mem::zeroed() };
let ret = unsafe { ffi::ANativeWindow_lock(self.ptr.as_ptr(), &mut out, dirty_bounds) };
status_to_io_result(ret, NativeWindowBufferLockGuard(out, self))
}
}

/// Lock holding the next drawing surface for writing. It is unlocked and posted on [`drop()`].
#[derive(Debug)]
pub struct NativeWindowBufferLockGuard<'a>(ffi::ANativeWindow_Buffer, &'a NativeWindow);

impl<'a> NativeWindowBufferLockGuard<'a> {
/// The number of pixels that are shown horizontally.
pub fn width(&self) -> i32 {
self.0.width
}

// The number of pixels that are shown vertically.
pub fn height(&self) -> i32 {
self.0.height
}

/// The number of _pixels_ that a line in the buffer takes in memory.
///
/// This may be `>= width`.
pub fn stride(&self) -> i32 {
self.0.stride
}

/// The format of the buffer. One of [`HardwareBufferFormat`].
pub fn format(&self) -> HardwareBufferFormat {
unsafe { std::mem::transmute(self.0.format) }
}

/// The actual bits.
pub fn bits(&mut self) -> *mut std::ffi::c_void {
self.0.bits
}
}

impl<'a> Drop for NativeWindowBufferLockGuard<'a> {
fn drop(&mut self) {
let ret = unsafe { ffi::ANativeWindow_unlockAndPost(self.1.ptr.as_ptr()) };
assert_eq!(ret, 0);
}
}

0 comments on commit 5d5e25a

Please sign in to comment.