#![allow(unsafe_code)]
use core::ffi::{c_char, c_void};
use crate::render::Pixmap;
const WINDOW_FORMAT_RGBA_8888: i32 = 1;
#[repr(C)]
struct ANativeWindowBuffer {
width: i32,
height: i32,
stride: i32,
format: i32,
bits: *mut c_void,
reserved: [u32; 6],
}
#[link(name = "android")]
unsafe extern "C" {
fn ANativeWindow_setBuffersGeometry(
window: *mut c_void,
width: i32,
height: i32,
format: i32,
) -> i32;
fn ANativeWindow_lock(
window: *mut c_void,
out_buffer: *mut ANativeWindowBuffer,
in_out_dirty_bounds: *mut c_void,
) -> i32;
fn ANativeWindow_unlockAndPost(window: *mut c_void) -> i32;
pub fn ANativeWindow_getWidth(window: *mut c_void) -> i32;
pub fn ANativeWindow_getHeight(window: *mut c_void) -> i32;
}
#[repr(C)]
#[derive(Debug)]
pub struct ANativeActivityCallbacks {
pub on_start: Option<unsafe extern "C" fn(*mut ANativeActivity)>,
pub on_resume: Option<unsafe extern "C" fn(*mut ANativeActivity)>,
pub on_save_instance_state:
Option<unsafe extern "C" fn(*mut ANativeActivity, *mut usize) -> *mut c_void>,
pub on_pause: Option<unsafe extern "C" fn(*mut ANativeActivity)>,
pub on_stop: Option<unsafe extern "C" fn(*mut ANativeActivity)>,
pub on_destroy: Option<unsafe extern "C" fn(*mut ANativeActivity)>,
pub on_window_focus_changed: Option<unsafe extern "C" fn(*mut ANativeActivity, i32)>,
pub on_native_window_created: Option<unsafe extern "C" fn(*mut ANativeActivity, *mut c_void)>,
pub on_native_window_resized: Option<unsafe extern "C" fn(*mut ANativeActivity, *mut c_void)>,
pub on_native_window_redraw_needed:
Option<unsafe extern "C" fn(*mut ANativeActivity, *mut c_void)>,
pub on_native_window_destroyed: Option<unsafe extern "C" fn(*mut ANativeActivity, *mut c_void)>,
pub on_input_queue_created: Option<unsafe extern "C" fn(*mut ANativeActivity, *mut c_void)>,
pub on_input_queue_destroyed: Option<unsafe extern "C" fn(*mut ANativeActivity, *mut c_void)>,
pub on_content_rect_changed: Option<unsafe extern "C" fn(*mut ANativeActivity, *const c_void)>,
pub on_configuration_changed: Option<unsafe extern "C" fn(*mut ANativeActivity)>,
pub on_low_memory: Option<unsafe extern "C" fn(*mut ANativeActivity)>,
}
#[repr(C)]
#[derive(Debug)]
pub struct ANativeActivity {
pub callbacks: *mut ANativeActivityCallbacks,
pub vm: *mut c_void,
pub env: *mut c_void,
pub clazz: *mut c_void,
pub internal_data_path: *const c_char,
pub external_data_path: *const c_char,
pub sdk_version: i32,
pub instance: *mut c_void,
pub asset_manager: *mut c_void,
pub obb_path: *const c_char,
}
pub unsafe fn present_to_native_window(window: *mut c_void, pixmap: &Pixmap) -> bool {
if window.is_null() {
return false;
}
let size = pixmap.size();
let (w, h) = (size.width as i32, size.height as i32);
unsafe {
ANativeWindow_setBuffersGeometry(window, w, h, WINDOW_FORMAT_RGBA_8888);
let mut buf = ANativeWindowBuffer {
width: 0,
height: 0,
stride: 0,
format: 0,
bits: core::ptr::null_mut(),
reserved: [0; 6],
};
if ANativeWindow_lock(window, &mut buf, core::ptr::null_mut()) != 0 || buf.bits.is_null() {
return false;
}
let src = pixmap.as_bytes();
let src_stride = pixmap.stride();
let copy_w = (buf.width.min(w)) as usize * 4;
let rows = buf.height.min(h) as usize;
let dst_stride = buf.stride as usize * 4;
for y in 0..rows {
let s = &src[y * src_stride..y * src_stride + copy_w];
let d = (buf.bits as *mut u8).add(y * dst_stride);
core::ptr::copy_nonoverlapping(s.as_ptr(), d, copy_w);
}
ANativeWindow_unlockAndPost(window) == 0
}
}