Skip to content

Commit

Permalink
ndk/native_window: Use release/acquire fns for Drop and Clone
Browse files Browse the repository at this point in the history
Much like ALooper and AHardwareBuffer the reference counter of
ANativeWindow must be properly incremented on `Clone`, in turn allowing
us to also `_release` the window as soon as it is dropped.
  • Loading branch information
MarijnS95 committed Apr 8, 2022
1 parent 22a11ae commit 48b0aab
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 11 deletions.
15 changes: 9 additions & 6 deletions ndk-glue/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ pub unsafe fn init(

let activity = NativeActivity::from_ptr(activity);
ndk_context::initialize_android_context(activity.vm().cast(), activity.activity().cast());
NATIVE_ACTIVITY = Some(activity);
NATIVE_ACTIVITY.replace(activity);

let mut logpipe: [RawFd; 2] = Default::default();
libc::pipe(logpipe.as_mut_ptr());
Expand Down Expand Up @@ -207,7 +207,7 @@ pub unsafe fn init(

{
let mut locked_looper = LOOPER.lock().unwrap();
*locked_looper = Some(foreign);
locked_looper.replace(foreign);
signal_looper_ready.notify_one();
}

Expand Down Expand Up @@ -274,7 +274,10 @@ unsafe extern "C" fn on_window_focus_changed(
}

unsafe extern "C" fn on_window_created(activity: *mut ANativeActivity, window: *mut ANativeWindow) {
*NATIVE_WINDOW.write().unwrap() = Some(NativeWindow::from_ptr(NonNull::new(window).unwrap()));
NATIVE_WINDOW
.write()
.unwrap()
.replace(NativeWindow::clone_from_ptr(NonNull::new(window).unwrap()));
wake(activity, Event::WindowCreated);
}

Expand All @@ -299,7 +302,7 @@ unsafe extern "C" fn on_window_destroyed(
wake(activity, Event::WindowDestroyed);
let mut native_window_guard = NATIVE_WINDOW.write().unwrap();
assert_eq!(native_window_guard.as_ref().unwrap().ptr().as_ptr(), window);
*native_window_guard = None;
native_window_guard.take();
}

unsafe extern "C" fn on_input_queue_created(
Expand All @@ -312,7 +315,7 @@ unsafe extern "C" fn on_input_queue_created(
// future code cleans it up and sets it back to `None` again.
let looper = locked_looper.as_ref().expect("Looper does not exist");
input_queue.attach_looper(looper, NDK_GLUE_LOOPER_INPUT_QUEUE_IDENT);
*INPUT_QUEUE.write().unwrap() = Some(input_queue);
INPUT_QUEUE.write().unwrap().replace(input_queue);
wake(activity, Event::InputQueueCreated);
}

Expand All @@ -325,7 +328,7 @@ unsafe extern "C" fn on_input_queue_destroyed(
assert_eq!(input_queue_guard.as_ref().unwrap().ptr().as_ptr(), queue);
let input_queue = InputQueue::from_ptr(NonNull::new(queue).unwrap());
input_queue.detach_looper();
*input_queue_guard = None;
input_queue_guard.take();
}

unsafe extern "C" fn on_content_rect_changed(activity: *mut ANativeActivity, rect: *const ARect) {
Expand Down
1 change: 1 addition & 0 deletions ndk/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- ndk/hardware_buffer: Make `HardwareBuffer::as_ptr()` public for interop with Vulkan.
- **Breaking:** `Configuration::country()` now returns `None` when the country is unset (akin to `Configuration::language()`)
- Add `MediaCodec` and `MediaFormat` bindings ([#216](https://github.com/rust-windowing/android-ndk-rs/pull/216))
- ndk/native_window: Use `release`/`acquire` for `Drop` and `Clone` respectively

# 0.6.0 (2022-01-05)

Expand Down
4 changes: 2 additions & 2 deletions ndk/src/media/media_codec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,13 +380,13 @@ impl MediaCodec {
}

#[cfg(feature = "api-level-26")]
pub fn set_input_surface(&self, surface: NativeWindow) -> Result<()> {
pub fn set_input_surface(&self, surface: &NativeWindow) -> Result<()> {
let status =
unsafe { ffi::AMediaCodec_setInputSurface(self.as_ptr(), surface.ptr().as_ptr()) };
NdkMediaError::from_status(status)
}

pub fn set_output_surface(&self, surface: NativeWindow) -> Result<()> {
pub fn set_output_surface(&self, surface: &NativeWindow) -> Result<()> {
let status =
unsafe { ffi::AMediaCodec_setOutputSurface(self.as_ptr(), surface.ptr().as_ptr()) };
NdkMediaError::from_status(status)
Expand Down
32 changes: 29 additions & 3 deletions ndk/src/native_window.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,47 @@
//! Bindings for `ANativeWindow`
//! Bindings for [`ffi::ANativeWindow`]
use std::ptr::NonNull;

#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[derive(Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct NativeWindow {
ptr: NonNull<ffi::ANativeWindow>,
}

unsafe impl Send for NativeWindow {}
unsafe impl Sync for NativeWindow {}

impl Drop for NativeWindow {
fn drop(&mut self) {
unsafe { ffi::ANativeWindow_release(self.ptr.as_ptr()) }
}
}

impl Clone for NativeWindow {
fn clone(&self) -> Self {
unsafe {
ffi::ANativeWindow_acquire(self.ptr.as_ptr());
Self { ptr: self.ptr }
}
}
}

impl NativeWindow {
/// Assumes ownership of `ptr`
///
/// # Safety
/// `ptr` must be a valid pointer to an Android `ANativeWindow`.
/// `ptr` must be a valid pointer to an Android [`ffi::ANativeWindow`].
pub unsafe fn from_ptr(ptr: NonNull<ffi::ANativeWindow>) -> Self {
Self { ptr }
}

/// Acquires ownership of `ptr`
///
/// # Safety
/// `ptr` must be a valid pointer to an Android [`ffi::ANativeWindow`].
pub unsafe fn clone_from_ptr(ptr: NonNull<ffi::ANativeWindow>) -> Self {
ffi::ANativeWindow_acquire(ptr.as_ptr());
Self::from_ptr(ptr)
}

pub fn ptr(&self) -> NonNull<ffi::ANativeWindow> {
self.ptr
}
Expand Down

0 comments on commit 48b0aab

Please sign in to comment.