#[cfg(not(target_family = "wasm"))]
#[path = "utils/winit_app.rs"]
mod winit_app;
#[cfg(not(target_family = "wasm"))]
pub mod ex {
use std::num::NonZeroU32;
use std::sync::{mpsc, Arc, Mutex};
use winit::event::{KeyEvent, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop, OwnedDisplayHandle};
use winit::keyboard::{Key, NamedKey};
use winit::window::Window;
use super::winit_app;
type Surface = softbuffer::Surface<OwnedDisplayHandle, Arc<Window>>;
fn render_thread(
do_render: mpsc::Receiver<(Arc<Mutex<Surface>>, NonZeroU32, NonZeroU32)>,
done: mpsc::Sender<()>,
) {
loop {
println!("waiting for render...");
let Ok((surface, width, height)) = do_render.recv() else {
println!("main thread destroyed");
break;
};
let mut surface = surface.lock().unwrap();
println!("resizing...");
surface.resize(width, height).unwrap();
let mut buffer = surface.buffer_mut().unwrap();
for y in 0..buffer.height().get() {
for x in 0..buffer.width().get() {
let red = x % 255;
let green = y % 255;
let blue = (x * y) % 255;
let index = y * buffer.width().get() + x;
buffer[index as usize] = blue | (green << 8) | (red << 16);
}
}
println!("presenting...");
buffer.present().unwrap();
done.send(()).ok();
}
}
pub fn entry(event_loop: EventLoop<()>) {
let context = softbuffer::Context::new(event_loop.owned_display_handle()).unwrap();
let app = winit_app::WinitAppBuilder::with_init(
|elwt| {
let attributes = Window::default_attributes();
#[cfg(target_family = "wasm")]
let attributes =
winit::platform::web::WindowAttributesExtWebSys::with_append(attributes, true);
let window = Arc::new(elwt.create_window(attributes).unwrap());
let (start_render, do_render) = mpsc::channel();
let (render_done, finish_render) = mpsc::channel();
println!("starting thread...");
std::thread::spawn(move || render_thread(do_render, render_done));
(window, start_render, finish_render)
},
move |_elwt, (window, _start_render, _finish_render)| {
println!("making surface...");
Arc::new(Mutex::new(
softbuffer::Surface::new(&context, window.clone()).unwrap(),
))
},
)
.with_event_handler(|state, surface, window_id, event, elwt| {
let (window, start_render, finish_render) = state;
elwt.set_control_flow(ControlFlow::Wait);
if window_id != window.id() {
return;
}
match event {
WindowEvent::RedrawRequested => {
let Some(surface) = surface else {
eprintln!("RedrawRequested fired before Resumed or after Suspended");
return;
};
let size = window.inner_size();
println!("got size: {size:?}");
if let (Some(width), Some(height)) =
(NonZeroU32::new(size.width), NonZeroU32::new(size.height))
{
start_render.send((surface.clone(), width, height)).unwrap();
finish_render.recv().unwrap();
}
}
WindowEvent::CloseRequested
| WindowEvent::KeyboardInput {
event:
KeyEvent {
logical_key: Key::Named(NamedKey::Escape),
..
},
..
} => {
elwt.exit();
}
_ => {}
}
});
winit_app::run_app(event_loop, app);
}
}
#[cfg(target_family = "wasm")]
mod ex {
use winit::event_loop::EventLoop;
pub(crate) fn entry(_event_loop: EventLoop<()>) {
eprintln!("winit_multithreaded doesn't work on WASM");
}
}
#[cfg(not(target_os = "android"))]
fn main() {
use winit::event_loop::EventLoop;
ex::entry(EventLoop::new().unwrap())
}