use core::ffi::{c_int, c_void};
use log::debug;
use ohos_vsync_sys::{
OH_NativeVSync, OH_NativeVSync_Create, OH_NativeVSync_Destroy, OH_NativeVSync_FrameCallback,
OH_NativeVSync_GetPeriod, OH_NativeVSync_RequestFrame,
};
mod log;
pub struct NativeVsync {
raw: *mut OH_NativeVSync,
}
#[derive(Debug)]
pub enum NativeVsyncError {
InvalidArgs,
CreateFailed,
RawErr(c_int),
}
impl NativeVsync {
pub fn new(name: &str) -> Result<Self, NativeVsyncError> {
let name_len: u32 = name
.len()
.try_into()
.map_err(|_| NativeVsyncError::InvalidArgs)?;
let raw = unsafe { OH_NativeVSync_Create(name.as_ptr().cast(), name_len) };
Ok(NativeVsync { raw })
}
pub unsafe fn from_raw(native_vsync: *mut OH_NativeVSync) -> Self {
debug_assert!(!native_vsync.is_null());
debug_assert!(native_vsync.is_aligned());
Self { raw: native_vsync }
}
pub fn into_raw(self) -> *mut OH_NativeVSync {
let raw = self.raw;
core::mem::forget(self);
raw
}
pub unsafe fn request_raw_callback(
&self,
callback: OH_NativeVSync_FrameCallback,
data: *mut c_void,
) -> Result<(), NativeVsyncError> {
let res = unsafe { OH_NativeVSync_RequestFrame(self.raw, callback, data) };
if res == 0 {
Ok(())
} else {
Err(NativeVsyncError::RawErr(res))
}
}
pub unsafe fn request_raw_callback_with_self(
self,
callback: OH_NativeVSync_FrameCallback,
) -> Result<(), NativeVsyncError> {
let res =
unsafe { OH_NativeVSync_RequestFrame(self.raw, callback, self.raw as *mut c_void) };
if res == 0 {
core::mem::forget(self);
Ok(())
} else {
Err(NativeVsyncError::RawErr(res))
}
}
pub fn get_period(&self) -> Result<u64, NativeVsyncError> {
let period = unsafe {
let mut period: i64 = -1;
let res = OH_NativeVSync_GetPeriod(self.raw, (&mut period) as *mut i64);
if res == 0 {
debug_assert!(period > 0, "Period must be a positive non-zero integer");
period as u64
} else {
debug!("OH_NativeVSync_GetPeriod failed with {res}");
return Err(NativeVsyncError::RawErr(res));
}
};
Ok(period)
}
}
impl Drop for NativeVsync {
fn drop(&mut self) {
unsafe { OH_NativeVSync_Destroy(self.raw) };
}
}