This example demonstrates how to integrate Softbuffer with winit to create a window and render a dynamic color pattern using Surface::next_buffer() and Buffer::present().
use std::num::NonZeroU32;
use std::rc::Rc;
use softbuffer::{Context, Pixel, Surface};
use winit::application::ApplicationHandler;
use winit::event::{StartCause, WindowEvent};
use winit::event_loop::{ActiveEventLoop, EventLoop, OwnedDisplayHandle};
use winit::window::{Window, WindowId};
fn main() {
let event_loop = EventLoop::new().unwrap();
let context = Context::new(event_loop.owned_display_handle()).unwrap();
let mut app = App {
context,
state: AppState::Initial,
};
event_loop.run_app(&mut app).unwrap();
}
#[derive(Debug)]
struct App {
context: Context<OwnedDisplayHandle>,
state: AppState,
}
#[derive(Debug)]
enum AppState {
Initial,
Suspended {
window: Rc<Window>,
},
Running {
surface: Surface<OwnedDisplayHandle, Rc<Window>>,
},
}
impl ApplicationHandler for App {
fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: StartCause) {
if let StartCause::Init = cause {
let window_attrs = Window::default_attributes();
let window = event_loop
.create_window(window_attrs)
.expect("failed creating window");
self.state = AppState::Suspended {
window: Rc::new(window),
};
}
}
fn resumed(&mut self, _event_loop: &ActiveEventLoop) {
let AppState::Suspended { window } = &mut self.state else {
unreachable!("got resumed event while not suspended");
};
let mut surface =
Surface::new(&self.context, window.clone()).expect("failed creating surface");
let size = window.inner_size();
if let (Some(width), Some(height)) =
(NonZeroU32::new(size.width), NonZeroU32::new(size.height))
{
surface.resize(width, height).unwrap();
}
self.state = AppState::Running { surface };
}
fn suspended(&mut self, _event_loop: &ActiveEventLoop) {
let AppState::Running { surface } = &mut self.state else {
unreachable!("got resumed event while not running");
};
let window = surface.window().clone();
self.state = AppState::Suspended { window };
}
fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
window_id: WindowId,
event: WindowEvent
) {
let AppState::Running { surface } = &mut self.state else {
unreachable!("got window event while suspended");
};
if surface.window().id() != window_id {
return;
}
match event {
WindowEvent::Resized(size) => {
if let (Some(width), Some(height)) =
(NonZeroU32::new(size.width), NonZeroU32::new(size.height))
{
surface.resize(width, height).unwrap();
}
}
WindowEvent::RedrawRequested => {
let mut buffer = surface.next_buffer().unwrap();
for (x, y, pixel) in buffer.pixels_iter() {
let red = (x % 255) as u8;
let green = (y % 255) as u8;
let blue = ((x * y) % 255) as u8;
*pixel = Pixel::new_rgb(red, green, blue);
}
buffer.present().unwrap();
}
WindowEvent::CloseRequested => {
event_loop.exit();
}
_ => {}
}
}
}