From 56f7986a3f7c898877a821f8d015c73f8dcdb0a5 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Wed, 16 Aug 2023 01:34:15 +0200 Subject: [PATCH] Return `SyncFence`'d `HardwareBuffer` to Java --- android_native_surface/Cargo.toml | 4 +- android_native_surface/src/lib.rs | 64 ++++++++++++++++++- .../rust/androidnativesurface/MainActivity.kt | 32 ++++++++++ 3 files changed, 97 insertions(+), 3 deletions(-) diff --git a/android_native_surface/Cargo.toml b/android_native_surface/Cargo.toml index d00b6cf..448e8ad 100644 --- a/android_native_surface/Cargo.toml +++ b/android_native_surface/Cargo.toml @@ -12,9 +12,9 @@ android_logger = "0.13" glutin = { version = "0.31", default-features = false, features = ["egl"] } jni = "0.21" log = "0.4" -ndk = { version = "0.8", default-features = false, features = ["api-level-28", "rwh_05"] } +ndk = { version = "0.8", default-features = false, features = ["api-level-28", "media", "sync", "rwh_05"] } raw-window-handle = "0.5" -rustix = { version = "0.38", default-features = false, features = ["std", "pipe", "stdio"] } +rustix = { version = "0.38", default-features = false, features = ["std", "event", "pipe", "stdio"] } [build-dependencies] gl_generator = "0.14" diff --git a/android_native_surface/src/lib.rs b/android_native_surface/src/lib.rs index 40af0df..d9b1a10 100644 --- a/android_native_surface/src/lib.rs +++ b/android_native_surface/src/lib.rs @@ -1,7 +1,9 @@ use std::{ fs::File, io::{self, BufRead, BufReader}, + os::fd::{AsFd, FromRawFd, RawFd}, thread, + time::Instant, }; use glutin::{ @@ -13,8 +15,15 @@ use jni::{ JNIEnv, }; use log::{debug, info, LevelFilter}; -use ndk::{native_window::NativeWindow, surface_texture::SurfaceTexture}; +use ndk::{ + hardware_buffer::HardwareBufferUsage, + media::image_reader::{ImageFormat, ImageReader}, + native_window::NativeWindow, + surface_texture::SurfaceTexture, + sync::SyncFileInfo, +}; use raw_window_handle::{AndroidDisplayHandle, HasRawWindowHandle, RawDisplayHandle}; +use rustix::event::{PollFd, PollFlags}; mod support; @@ -148,3 +157,56 @@ pub extern "system" fn Java_rust_androidnativesurface_MainActivity_00024Companio render_to_native_window(window) } + +#[no_mangle] +pub extern "system" fn Java_rust_androidnativesurface_MainActivity_00024Companion_renderHardwareBuffer( + mut env: JNIEnv, + _class: JClass, +) { + debug!("SurfaceControl hack"); + + let cls = env + .find_class("rust/androidnativesurface/RenderedHardwareBuffer") + .unwrap(); + dbg!(cls); + let image_reader = ImageReader::new(100, 100, ImageFormat::RGBA_8888, 10).expect("ImageReader"); + let window = image_reader.window().expect("NativeWindow"); + dbg!(&image_reader, &window); + + debug!( + "Acquire before {:?}", + image_reader.acquire_latest_image_async() + ); + + render_to_native_window(window); + + let (image, fd) = image_reader.acquire_latest_image_async().unwrap(); + dbg!(&image, &fd); + + if let Some(fd) = &fd { + let sync_file_info = SyncFileInfo::new(fd.as_fd()).expect("SyncFileInfo"); + dbg!(&sync_file_info); + } + + let hwbuf = image.hardware_buffer().unwrap(); + dbg!(&hwbuf); + dbg!(hwbuf.describe()); + + if let Some(fd) = &fd { + let x = Instant::now(); + let mut pfd = PollFd::new(fd, PollFlags::all()); + rustix::event::poll(std::slice::from_mut(&mut pfd), -1).unwrap(); + debug!("Polling on fd took {:.3?}: {pfd:?}", x.elapsed()); + } + let x = Instant::now(); + // let map = hwbuf.lock(HardwareBufferUsage::CPU_READ_OFTEN, None, None); + let map = hwbuf.lock(HardwareBufferUsage::CPU_READ_OFTEN, fd, None); + debug!("Locking with fd took {:.3?}", x.elapsed()); + debug!("map {:?}", map); + debug!("unlock async {:?}", hwbuf.unlock_async()); + + // let obj = env.alloc_object(cls).unwrap(); + // dbg!(obj); + // env.new_object(cls, ctor_sig, ctor_args) + // hwbuf.to_jni(env) +} diff --git a/app/src/main/java/rust/androidnativesurface/MainActivity.kt b/app/src/main/java/rust/androidnativesurface/MainActivity.kt index 1558e3f..d1bfd04 100644 --- a/app/src/main/java/rust/androidnativesurface/MainActivity.kt +++ b/app/src/main/java/rust/androidnativesurface/MainActivity.kt @@ -2,11 +2,22 @@ package rust.androidnativesurface import android.app.Activity import android.graphics.SurfaceTexture +import android.hardware.HardwareBuffer +import android.hardware.SyncFence import android.os.Bundle +import android.os.ParcelFileDescriptor import android.view.Surface +import android.view.SurfaceControl import android.view.SurfaceHolder import android.view.SurfaceView import android.view.TextureView +import java.io.FileDescriptor + +data class RenderedHardwareBuffer( + val hardware_buffer: HardwareBuffer, + val fd: Int +) + class MainActivity : Activity() { companion object { @@ -18,6 +29,8 @@ class MainActivity : Activity() { private external fun init() external fun renderToSurface(surface: Surface) external fun renderToSurfaceTexture(surfaceTexture: SurfaceTexture) + + external fun renderHardwareBuffer() // : RenderedHardwareBuffer } override fun onCreate(savedInstanceState: Bundle?) { @@ -26,9 +39,28 @@ class MainActivity : Activity() { val surfaceView: SurfaceView = findViewById(R.id.surface_view) println("SurfaceView: ${surfaceView.holder.surface}") + + + renderHardwareBuffer() +// +// val hwbuf = renderHardwareBuffer() +// println("Have HardwareBuffer ${hwbuf.hardware_buffer}, wait for fd ${hwbuf.fd}") +// val t = SurfaceControl.Transaction() +// +// // TODO: This is @hide :( +// val f = SyncFence.create(ParcelFileDescriptor.adoptFd(hwbuf.fd)) +// println("Fence $f") +// t.setBuffer( +// surfaceView.surfaceControl, +// hwbuf.hardware_buffer, +// f +// ) + return + surfaceView.holder.addCallback(object : SurfaceHolder.Callback { override fun surfaceCreated(holder: SurfaceHolder) { println("SurfaceView created: ${holder.surface}") +// holder.surface.attachAndQueueBufferWithColorSpace() renderToSurface(holder.surface) }