use glow::HasContext;
fn main() {
use glfw_sys::*;
use std::ffi::CStr;
unsafe {
let mut description: *const i8 = std::ptr::null();
if glfwInit() != GLFW_TRUE {
glfwGetError(&mut description);
panic!(
"Error: {:?}\n",
description
.is_null()
.then_some(c"")
.unwrap_or_else(|| CStr::from_ptr(description))
);
}
println!("Initialized GLFW");
let win = glfwCreateWindow(
600,
400,
c"Single-Window Example".as_ptr(),
std::ptr::null_mut(),
std::ptr::null_mut(),
);
if win.is_null() {
glfwGetError(&mut description);
println!(
"Error: {:?}\n",
description
.is_null()
.then_some(c"")
.unwrap_or_else(|| CStr::from_ptr(description))
);
glfwTerminate();
panic!();
}
println!("Created GLFW window with handle: {:?}", win);
glfwMakeContextCurrent(win);
let ctx = glow::Context::from_loader_function_cstr(|s| {
glfwGetProcAddress(s.as_ptr())
.map(|p| p as _)
.unwrap_or(std::ptr::null())
});
println!("Created OpenGL context with handle: {:?}\n", ctx);
set_main_loop_callback(move || {
let time = glfwGetTime() as f32;
ctx.clear_color(time.sin(), time.cos(), time.tan(), 1.0);
ctx.clear(glow::COLOR_BUFFER_BIT);
glfwSwapBuffers(win);
glfwPollEvents();
if glfwGetKey(win, GLFW_KEY_ESCAPE) == GLFW_TRUE {
println!("Terminating main loop");
glfwMakeContextCurrent(std::ptr::null_mut());
glfwDestroyWindow(win);
glfwTerminate();
emscripten_cancel_main_loop();
}
});
}
}
#[allow(non_camel_case_types)]
type em_callback_func = unsafe extern "C" fn();
#[allow(unused)]
const CANVAS_ELEMENT_NAME: *const std::ffi::c_char = "#canvas\0".as_ptr() as _;
extern "C" {
pub fn emscripten_cancel_main_loop();
pub fn emscripten_set_main_loop(
func: em_callback_func,
fps: std::ffi::c_int,
simulate_infinite_loop: std::ffi::c_int,
);
}
thread_local!(static MAIN_LOOP_CALLBACK: std::cell::RefCell<Option<Box<dyn FnMut()>>> = std::cell::RefCell::new(None));
pub fn set_main_loop_callback<F: 'static>(callback: F)
where
F: FnMut(),
{
MAIN_LOOP_CALLBACK.with(|log| {
*log.borrow_mut() = Some(Box::new(callback));
});
unsafe {
emscripten_set_main_loop(wrapper::<F>, 0, 1);
}
#[allow(clippy::extra_unused_type_parameters)]
extern "C" fn wrapper<F>()
where
F: FnMut(),
{
MAIN_LOOP_CALLBACK.with(|z| {
if let Some(ref mut callback) = *z.borrow_mut() {
callback();
}
});
}
}