diff --git a/src/main.rs b/src/main.rs index 8a6dd95..9f5cbaf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,24 +4,99 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use glow::HasContext; +use glow::{Context, HasContext, NativeProgram, NativeVertexArray}; use glutin::{ config::{ConfigSurfaceTypes, ConfigTemplateBuilder}, - context::{ContextAttributesBuilder, GlProfile}, + context::{ContextAttributesBuilder, GlProfile, PossiblyCurrentContext}, display::GetGlDisplay, prelude::*, - surface::{SurfaceAttributesBuilder, WindowSurface}, + surface::{Surface, SurfaceAttributesBuilder, WindowSurface}, }; use glutin_winit::DisplayBuilder; use raw_window_handle::HasRawWindowHandle; -use std::ffi::CString; +use std::{error::Error, ffi::CString}; use winit::{ - event::{Event, WindowEvent}, - event_loop::{ControlFlow, EventLoop}, - window::Window, + application::ApplicationHandler, + event::WindowEvent, + event_loop::{ActiveEventLoop, ControlFlow, EventLoop}, + window::{Window, WindowId}, }; -fn main() { +struct App { + window: Window, + gl_surface: Surface, + gl_context: PossiblyCurrentContext, + gl: Context, + vao: NativeVertexArray, + program: NativeProgram, +} + +impl App { + fn new( + window: Window, + gl_surface: Surface, + gl_context: PossiblyCurrentContext, + gl: Context, + vao: NativeVertexArray, + program: NativeProgram, + ) -> App { + App { + window, + gl_surface, + gl_context, + gl, + vao, + program, + } + } +} + +impl ApplicationHandler for App { + fn resumed(&mut self, _event_loop: &ActiveEventLoop) { + self.window.request_redraw(); + } + + fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) { + match event { + WindowEvent::CloseRequested => event_loop.exit(), + WindowEvent::Resized(size) => { + // Update the surface size + self.gl_surface.resize( + &self.gl_context, + std::num::NonZeroU32::new(size.width).unwrap(), + std::num::NonZeroU32::new(size.height).unwrap(), + ); + + // Update the viewport + unsafe { + self.gl + .viewport(0, 0, size.width as i32, size.height as i32); + } + + self.window.request_redraw(); + } + WindowEvent::RedrawRequested => { + // Clear the screen + unsafe { + self.gl.clear(glow::COLOR_BUFFER_BIT); + + // Draw our triangle + self.gl.use_program(Some(self.program)); + self.gl.bind_vertex_array(Some(self.vao)); + self.gl.draw_arrays(glow::TRIANGLES, 0, 3); + } + + // Swap buffers + self.gl_surface + .swap_buffers(&self.gl_context) + .expect("Failed to swap buffers"); + } + _ => (), + } + } +} + +fn main() -> Result<(), Box> { // Create an event loop let event_loop = EventLoop::new().unwrap(); event_loop.set_control_flow(ControlFlow::Poll); @@ -59,7 +134,7 @@ fn main() { // Create OpenGL context attributes let context_attributes = ContextAttributesBuilder::new() .with_profile(GlProfile::Core) - .build(window.raw_window_handle().ok()); + .build(None); // Create the OpenGL surface attributes let surface_attributes = SurfaceAttributesBuilder::::new().build( @@ -212,47 +287,7 @@ fn main() { (program, vao) }; - // Run the event loop - event_loop - .run(move |event, event_loop| { - match event { - Event::WindowEvent { event, .. } => match event { - WindowEvent::CloseRequested => event_loop.exit(), - WindowEvent::Resized(size) => { - // Update the surface size - gl_surface.resize( - &gl_context, - std::num::NonZeroU32::new(size.width).unwrap(), - std::num::NonZeroU32::new(size.height).unwrap(), - ); - - // Update the viewport - unsafe { - gl.viewport(0, 0, size.width as i32, size.height as i32); - } - - window.request_redraw(); - } - WindowEvent::RedrawRequested => { - // Clear the screen - unsafe { - gl.clear(glow::COLOR_BUFFER_BIT); - - // Draw our triangle - gl.use_program(Some(program)); - gl.bind_vertex_array(Some(vao)); - gl.draw_arrays(glow::TRIANGLES, 0, 3); - } - - // Swap buffers - gl_surface - .swap_buffers(&gl_context) - .expect("Failed to swap buffers"); - } - _ => (), - }, - _ => (), - } - }) - .unwrap(); + let mut app = App::new(window, gl_surface, gl_context, gl, vao, program); + event_loop.run_app(&mut app)?; + Ok(()) }