|
- use glutin::{
- dpi::{PhysicalPosition, PhysicalSize},
- event_loop::EventLoop,
- monitor::VideoMode,
- window::{Fullscreen, Window as GlutinWindow, WindowBuilder},
- Api, ContextBuilder, ContextWrapper, GlProfile, GlRequest, PossiblyCurrent,
- };
- use log::{error, info};
-
- use crate::{resources::Config, Error};
-
- pub struct Window {
- context: ContextWrapper<PossiblyCurrent, GlutinWindow>,
- }
-
- impl Window {
- pub fn new<T>(event_loop: &EventLoop<T>, config: &Config) -> Result<Self, Error> {
- let monitor = event_loop
- .primary_monitor()
- .or_else(|| event_loop.available_monitors().next());
-
- let (fullscreen, border) = match (config.video.windowed, config.video.fullscreen) {
- (false, true) => {
- let mut video_mode: Option<VideoMode> = None;
-
- if let Some(monitor) = monitor {
- for mode in monitor.video_modes() {
- video_mode = Some(match video_mode {
- Some(current) => {
- if mode.size().width <= config.video.resolution.0
- && mode.size().height <= config.video.resolution.1
- && mode.size().width >= current.size().width
- && mode.size().height >= current.size().height
- && mode.bit_depth() >= current.bit_depth()
- && mode.refresh_rate() >= current.refresh_rate()
- {
- mode
- } else {
- current
- }
- }
- None => mode,
- });
- }
- }
-
- match video_mode {
- Some(video_mode) => (Some(Fullscreen::Exclusive(video_mode)), false),
- None => {
- error!("Unable to find video mode for exclusive fullscreen!");
-
- (Some(Fullscreen::Borderless(None)), false)
- }
- }
- }
- (true, true) => (Some(Fullscreen::Borderless(None)), false),
- (false, false) => (None, false),
- (true, false) => (None, true),
- };
-
- let mut multisampling = [16u16, 8, 4, 2, 1, 0].iter();
- let context = loop {
- let multisampling = match multisampling.next() {
- Some(multisampling) => *multisampling,
- None => return Err(Error::CreateContext),
- };
-
- if config.video.multisampling < multisampling {
- continue;
- }
-
- info!("Create OpenGL context (multisampling={})", multisampling);
-
- let window_builder = WindowBuilder::new()
- .with_title("space-crush")
- .with_visible(true)
- .with_decorations(border)
- .with_fullscreen(fullscreen.clone())
- .with_inner_size::<PhysicalSize<u32>>(config.video.resolution.into());
- let ret = ContextBuilder::new()
- .with_double_buffer(Some(true))
- .with_hardware_acceleration(Some(true))
- .with_pixel_format(24, 8)
- .with_multisampling(multisampling)
- .with_vsync(false)
- .with_gl(GlRequest::Specific(Api::OpenGl, (4, 5)))
- .with_gl_profile(GlProfile::Core)
- .build_windowed(window_builder, event_loop);
-
- if let Ok(context) = ret {
- break context;
- }
- };
-
- let window = context.window();
- let window_size = window.outer_size();
- let monitor_size = window.current_monitor().unwrap().size();
- window.set_outer_position(PhysicalPosition::new(
- (monitor_size.width - window_size.width) / 2,
- (monitor_size.height - window_size.height) / 2,
- ));
-
- let context = unsafe { context.make_current().unwrap() };
- gl::load_with(|s| context.get_proc_address(s));
-
- gl::disable(gl::CULL_FACE);
- gl::disable(gl::DEPTH_TEST);
- gl::clear_color(0.1, 0.1, 0.1, 1.0);
- gl::pixel_store_i(gl::UNPACK_ALIGNMENT, 1);
-
- Ok(Self { context })
- }
-
- pub fn swap_buffers(&self) -> Result<(), Error> {
- self.context.swap_buffers()?;
-
- Ok(())
- }
- }
|