use std::sync::{Arc, Condvar, Mutex};
use std::time::Instant;
#[link(name = "dwmapi")]
unsafe extern "system" {
fn DwmFlush() -> i32;
}
static ARMED: Mutex<bool> = Mutex::new(false);
static WAKE: Condvar = Condvar::new();
pub(super) fn install() {
let started = std::thread::Builder::new()
.name("stipple-vsync".into())
.spawn(run)
.is_ok();
if !started {
return; }
crate::platform::frame::install(
Arc::new(|| {
*ARMED.lock().unwrap_or_else(|e| e.into_inner()) = true;
WAKE.notify_one();
}),
None,
);
}
fn run() {
let mut last = Instant::now();
loop {
{
let mut armed = ARMED.lock().unwrap_or_else(|e| e.into_inner());
while !*armed {
armed = WAKE.wait(armed).unwrap_or_else(|e| e.into_inner());
}
*armed = false;
}
let ok = unsafe { DwmFlush() } >= 0;
let interval = crate::platform::frame::interval();
let spacing = if ok { interval / 2 } else { interval };
let since = last.elapsed();
if since < spacing {
std::thread::sleep(spacing - since);
}
last = Instant::now();
crate::platform::frame::tick();
}
}