Extract render module
Description
There are a lot of details that go into setting up an OpenGL context, including several unsafe calls. This change extracts everything related to drawing to a new module to keep the main function simpler.
Right now it doesn't handle any errors, we can improve on that later if needed.
Commands
git clone git@github.com:atsheehan/iridium
cd iridium
git checkout 79583357969ce5ffc185eab9154fc903b3b21165
cargo run --release
Code Changes
Modified src/main.rsGitHub
@@ -1,76 +1,29 @@1- use std::ffi::CString;
1+ mod render;
22
3- use glutin::{
4- config::ConfigTemplateBuilder,
5- context::{ContextApi, ContextAttributesBuilder, Version},
6- display::GetGlDisplay,
7- prelude::{GlDisplay, NotCurrentGlContext},
8- surface::{GlSurface, SurfaceAttributesBuilder},
9- };
10- use glutin_winit::{DisplayBuilder, GlWindow};
11- use raw_window_handle::HasRawWindowHandle;
3+ use render::Renderer;
124 use winit::{
135 event::{Event, WindowEvent},
146 event_loop::EventLoop,
15- window::WindowBuilder,
167 };
178
189 fn main() {
1910 let event_loop = EventLoop::new().unwrap();
20- let window_builder = WindowBuilder::new().with_title("iridium");
21-
22- let config_template = ConfigTemplateBuilder::default();
23- let (window, config) = DisplayBuilder::new()
24- .with_window_builder(Some(window_builder))
25- .build(&event_loop, config_template, |mut configs| {
26- configs.next().unwrap()
27- })
28- .unwrap();
29- let window = window.unwrap();
30- let display = config.display();
31-
32- let context_attributes = ContextAttributesBuilder::new()
33- .with_context_api(ContextApi::OpenGl(Some(Version::new(3, 0))))
34- .build(Some(window.raw_window_handle()));
35-
36- let surface_attributes = window.build_surface_attributes(SurfaceAttributesBuilder::default());
37- let surface = unsafe {
38- display
39- .create_window_surface(&config, &surface_attributes)
40- .unwrap()
41- };
42-
43- let context = unsafe {
44- display
45- .create_context(&config, &context_attributes)
46- .unwrap()
47- .make_current(&surface)
48- .unwrap()
49- };
50-
51- gl::load_with(|s| display.get_proc_address(&CString::new(s).unwrap()));
11+ let mut renderer = Renderer::new(&event_loop);
5212
53- unsafe {
54- gl::ClearColor(0.6, 0.4, 0.8, 1.0);
55- }
56-
5713 event_loop
5814 .run(move |event, window_target| match event {
5915 Event::WindowEvent {
6016 event: WindowEvent::CloseRequested,
6117 window_id,
62- } if window_id == window.id() => {
18+ } if window_id == renderer.window_id() => {
6319 window_target.exit();
6420 }
6521 Event::WindowEvent {
6622 event: WindowEvent::RedrawRequested,
6723 window_id,
68- } if window_id == window.id() => {
69- unsafe {
70- gl::Clear(gl::COLOR_BUFFER_BIT);
71- }
72-
73- surface.swap_buffers(&context).unwrap();
24+ } if window_id == renderer.window_id() => {
25+ renderer.clear();
26+ renderer.present();
7427 }
7528 _ => (),
7629 })
@@ -1,76 +1,29 @@1- use std::ffi::CString;
2
3- use glutin::{
4- config::ConfigTemplateBuilder,
5- context::{ContextApi, ContextAttributesBuilder, Version},
6- display::GetGlDisplay,
7- prelude::{GlDisplay, NotCurrentGlContext},
8- surface::{GlSurface, SurfaceAttributesBuilder},
9- };
10- use glutin_winit::{DisplayBuilder, GlWindow};
11- use raw_window_handle::HasRawWindowHandle;
12 use winit::{
13 event::{Event, WindowEvent},
14 event_loop::EventLoop,
15- window::WindowBuilder,
16 };
17
18 fn main() {
19 let event_loop = EventLoop::new().unwrap();
20- let window_builder = WindowBuilder::new().with_title("iridium");
21-
22- let config_template = ConfigTemplateBuilder::default();
23- let (window, config) = DisplayBuilder::new()
24- .with_window_builder(Some(window_builder))
25- .build(&event_loop, config_template, |mut configs| {
26- configs.next().unwrap()
27- })
28- .unwrap();
29- let window = window.unwrap();
30- let display = config.display();
31-
32- let context_attributes = ContextAttributesBuilder::new()
33- .with_context_api(ContextApi::OpenGl(Some(Version::new(3, 0))))
34- .build(Some(window.raw_window_handle()));
35-
36- let surface_attributes = window.build_surface_attributes(SurfaceAttributesBuilder::default());
37- let surface = unsafe {
38- display
39- .create_window_surface(&config, &surface_attributes)
40- .unwrap()
41- };
42-
43- let context = unsafe {
44- display
45- .create_context(&config, &context_attributes)
46- .unwrap()
47- .make_current(&surface)
48- .unwrap()
49- };
50-
51- gl::load_with(|s| display.get_proc_address(&CString::new(s).unwrap()));
52
53- unsafe {
54- gl::ClearColor(0.6, 0.4, 0.8, 1.0);
55- }
56-
57 event_loop
58 .run(move |event, window_target| match event {
59 Event::WindowEvent {
60 event: WindowEvent::CloseRequested,
61 window_id,
62- } if window_id == window.id() => {
63 window_target.exit();
64 }
65 Event::WindowEvent {
66 event: WindowEvent::RedrawRequested,
67 window_id,
68- } if window_id == window.id() => {
69- unsafe {
70- gl::Clear(gl::COLOR_BUFFER_BIT);
71- }
72-
73- surface.swap_buffers(&context).unwrap();
74 }
75 _ => (),
76 })
@@ -1,76 +1,29 @@1+ mod render;
2
3+ use render::Renderer;
4 use winit::{
5 event::{Event, WindowEvent},
6 event_loop::EventLoop,
7 };
8
9 fn main() {
10 let event_loop = EventLoop::new().unwrap();
11+ let mut renderer = Renderer::new(&event_loop);
12
13 event_loop
14 .run(move |event, window_target| match event {
15 Event::WindowEvent {
16 event: WindowEvent::CloseRequested,
17 window_id,
18+ } if window_id == renderer.window_id() => {
19 window_target.exit();
20 }
21 Event::WindowEvent {
22 event: WindowEvent::RedrawRequested,
23 window_id,
24+ } if window_id == renderer.window_id() => {
25+ renderer.clear();
26+ renderer.present();
27 }
28 _ => (),
29 })
Added src/render.rsGitHub
1+ use std::ffi::CString;2+ 3+ use glutin::{4+ config::ConfigTemplateBuilder,5+ context::{ContextApi, ContextAttributesBuilder, PossiblyCurrentContext, Version},6+ display::GetGlDisplay,7+ prelude::{GlDisplay, NotCurrentGlContext},8+ surface::{GlSurface, Surface, SurfaceAttributesBuilder, WindowSurface},9+ };10+ use glutin_winit::{DisplayBuilder, GlWindow};11+ use raw_window_handle::HasRawWindowHandle;12+ use winit::{13+ event_loop::EventLoop,14+ window::{Window, WindowBuilder, WindowId},15+ };16+ 17+ pub(crate) struct Renderer {18+ window: Window,19+ context: PossiblyCurrentContext,20+ surface: Surface<WindowSurface>,21+ }22+ 23+ impl Renderer {24+ pub(crate) fn new(event_loop: &EventLoop<()>) -> Self {25+ let window_builder = WindowBuilder::new().with_title("iridium");26+ 27+ let config_template = ConfigTemplateBuilder::default();28+ let (window, config) = DisplayBuilder::new()29+ .with_window_builder(Some(window_builder))30+ .build(event_loop, config_template, |mut configs| {31+ configs.next().unwrap()32+ })33+ .unwrap();34+ let window = window.unwrap();35+ let display = config.display();36+ 37+ let context_attributes = ContextAttributesBuilder::new()38+ .with_context_api(ContextApi::OpenGl(Some(Version::new(3, 0))))39+ .build(Some(window.raw_window_handle()));40+ 41+ let surface_attributes =42+ window.build_surface_attributes(SurfaceAttributesBuilder::default());43+ let surface = unsafe {44+ display45+ .create_window_surface(&config, &surface_attributes)46+ .unwrap()47+ };48+ 49+ let context = unsafe {50+ display51+ .create_context(&config, &context_attributes)52+ .unwrap()53+ .make_current(&surface)54+ .unwrap()55+ };56+ 57+ gl::load_with(|s| display.get_proc_address(&CString::new(s).unwrap()));58+ 59+ unsafe {60+ gl::ClearColor(0.6, 0.4, 0.8, 1.0);61+ }62+ 63+ Self {64+ window,65+ surface,66+ context,67+ }68+ }69+ 70+ pub(crate) fn window_id(&self) -> WindowId {71+ self.window.id()72+ }73+ 74+ pub(crate) fn clear(&mut self) {75+ unsafe {76+ gl::Clear(gl::COLOR_BUFFER_BIT);77+ }78+ }79+ 80+ pub(crate) fn present(&mut self) {81+ self.surface.swap_buffers(&self.context).unwrap();82+ }83+ }
1+ use std::ffi::CString;2+ 3+ use glutin::{4+ config::ConfigTemplateBuilder,5+ context::{ContextApi, ContextAttributesBuilder, PossiblyCurrentContext, Version},6+ display::GetGlDisplay,7+ prelude::{GlDisplay, NotCurrentGlContext},8+ surface::{GlSurface, Surface, SurfaceAttributesBuilder, WindowSurface},9+ };10+ use glutin_winit::{DisplayBuilder, GlWindow};11+ use raw_window_handle::HasRawWindowHandle;12+ use winit::{13+ event_loop::EventLoop,14+ window::{Window, WindowBuilder, WindowId},15+ };16+ 17+ pub(crate) struct Renderer {18+ window: Window,19+ context: PossiblyCurrentContext,20+ surface: Surface<WindowSurface>,21+ }22+ 23+ impl Renderer {24+ pub(crate) fn new(event_loop: &EventLoop<()>) -> Self {25+ let window_builder = WindowBuilder::new().with_title("iridium");26+ 27+ let config_template = ConfigTemplateBuilder::default();28+ let (window, config) = DisplayBuilder::new()29+ .with_window_builder(Some(window_builder))30+ .build(event_loop, config_template, |mut configs| {31+ configs.next().unwrap()32+ })33+ .unwrap();34+ let window = window.unwrap();35+ let display = config.display();36+ 37+ let context_attributes = ContextAttributesBuilder::new()38+ .with_context_api(ContextApi::OpenGl(Some(Version::new(3, 0))))39+ .build(Some(window.raw_window_handle()));40+ 41+ let surface_attributes =42+ window.build_surface_attributes(SurfaceAttributesBuilder::default());43+ let surface = unsafe {44+ display45+ .create_window_surface(&config, &surface_attributes)46+ .unwrap()47+ };48+ 49+ let context = unsafe {50+ display51+ .create_context(&config, &context_attributes)52+ .unwrap()53+ .make_current(&surface)54+ .unwrap()55+ };56+ 57+ gl::load_with(|s| display.get_proc_address(&CString::new(s).unwrap()));58+ 59+ unsafe {60+ gl::ClearColor(0.6, 0.4, 0.8, 1.0);61+ }62+ 63+ Self {64+ window,65+ surface,66+ context,67+ }68+ }69+ 70+ pub(crate) fn window_id(&self) -> WindowId {71+ self.window.id()72+ }73+ 74+ pub(crate) fn clear(&mut self) {75+ unsafe {76+ gl::Clear(gl::COLOR_BUFFER_BIT);77+ }78+ }79+ 80+ pub(crate) fn present(&mut self) {81+ self.surface.swap_buffers(&self.context).unwrap();82+ }83+ }