use std::sync::Once;
use std::sync::atomic::{AtomicUsize, Ordering};
use oxivgl::driver::LvglDriver;
use oxivgl::widgets::Screen;
static INIT: Once = Once::new();
static mut DRIVER: Option<LvglDriver> = None;
static INIT_THREAD: AtomicUsize = AtomicUsize::new(0);
pub fn ensure_init() {
let tid = thread_id();
let prev = INIT_THREAD.compare_exchange(0, tid, Ordering::SeqCst, Ordering::SeqCst);
match prev {
Ok(_) => {} Err(first_tid) => {
assert_eq!(
first_tid, tid,
"LVGL tests must run single-threaded (--test-threads=1). \
First init on thread {first_tid}, now called from {tid}."
);
}
}
INIT.call_once(|| {
assert!(
std::env::var("SDL_VIDEODRIVER").is_ok(),
"SDL_VIDEODRIVER not set — run via: ./run_tests.sh"
);
unsafe { DRIVER = Some(LvglDriver::init(320, 240)) };
});
}
pub fn fresh_screen() -> Screen {
ensure_init();
unsafe {
let new = oxivgl_sys::lv_obj_create(core::ptr::null_mut());
oxivgl_sys::lv_screen_load(new);
}
Screen::active().expect("no active screen after init")
}
pub fn pump() {
let driver = unsafe { (*core::ptr::addr_of!(DRIVER)).as_ref().unwrap() };
driver.timer_handler();
unsafe { oxivgl_sys::lv_refr_now(core::ptr::null_mut()) };
}
pub fn driver() -> &'static LvglDriver {
ensure_init();
unsafe { (*core::ptr::addr_of!(DRIVER)).as_ref().unwrap() }
}
fn thread_id() -> usize {
thread_local! { static ANCHOR: u8 = const { 0 }; }
ANCHOR.with(|a| a as *const u8 as usize)
}