From 93347346e8bd8f7412ae03a0858dd307a1df2e0d Mon Sep 17 00:00:00 2001 From: Micha White Date: Thu, 20 Oct 2022 20:39:44 -0400 Subject: Moved files into workspace --- alligator_render/src/config.rs | 193 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 alligator_render/src/config.rs (limited to 'alligator_render/src/config.rs') diff --git a/alligator_render/src/config.rs b/alligator_render/src/config.rs new file mode 100644 index 0000000..c73c357 --- /dev/null +++ b/alligator_render/src/config.rs @@ -0,0 +1,193 @@ +use std::num::NonZeroU32; + +use winit::dpi::{LogicalPosition, LogicalSize}; +use winit::window::{Fullscreen, WindowBuilder}; + +/// Describes how a window may be resized +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] +pub struct Resizable { + /// The minimum width of the window, or None if unconstrained + pub min_width: Option, + /// The minimum height of the window, or None if unconstrained + pub min_height: Option, + /// The maximum width of the window, or None if unconstrained + pub max_width: Option, + /// The maximum height of the window, or None if unconstrained + pub max_height: Option, +} + +/// Information about a window, that is not fullscreened +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct WindowInfo { + pub default_x: i32, + pub default_y: i32, + pub resizable: Option, + pub default_maximized: bool, +} + +impl Default for WindowInfo { + fn default() -> Self { + Self { + default_x: 100, + default_y: 100, + resizable: Some(Resizable::default()), + default_maximized: false, + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub enum WindowMode { + Windowed(WindowInfo), + // TODO support choosing a monitor + BorderlessFullscreen, // TODO exclusive fullscreen +} + +impl Default for WindowMode { + fn default() -> Self { + Self::Windowed(WindowInfo::default()) + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +// TODO window icon +pub struct RenderWindowConfig<'a> { + /// The width of the window, once initialized + pub default_width: NonZeroU32, + /// The height of the window, once initialized + pub default_height: NonZeroU32, + /// The window may be fullscreen + pub mode: WindowMode, + /// The title for the window + pub title: &'a str, + /// If true, a low-power device will be selected as the GPU, if possible + pub low_power: bool, + /// If true, Fifo mode is used to present frames. If false, then Mailbox or + /// Immediate will be used if available. Otherwise, Fifo will be used. + pub vsync: bool, + /// The initial capacity of the instance buffer. The size will increase if + /// it's not large enough. Increasing this value may improve performance + /// towards the beginning, if a lot of instances are being created. + pub instance_capacity: usize, +} + +impl<'a> Default for RenderWindowConfig<'a> { + fn default() -> Self { + Self { + default_width: NonZeroU32::new(640).unwrap(), + default_height: NonZeroU32::new(480).unwrap(), + mode: WindowMode::default(), + title: "Alligator Game", + low_power: true, + vsync: true, + instance_capacity: 0, // TODO this should probably be bigger + } + } +} + +impl<'a> RenderWindowConfig<'a> { + /// Based on the vsync settings, choose a presentation mode + pub(crate) fn present_mode( + vsync: bool, + supported_modes: &[wgpu::PresentMode], + ) -> wgpu::PresentMode { + if vsync { + wgpu::PresentMode::Fifo + } else if supported_modes.contains(&wgpu::PresentMode::Mailbox) { + wgpu::PresentMode::Mailbox + } else if supported_modes.contains(&wgpu::PresentMode::Immediate) { + wgpu::PresentMode::Immediate + } else { + wgpu::PresentMode::Fifo + } + } + + /// Pick an alpha mode + fn alpha_mode(supported_modes: &[wgpu::CompositeAlphaMode]) -> wgpu::CompositeAlphaMode { + if supported_modes.contains(&wgpu::CompositeAlphaMode::PostMultiplied) { + wgpu::CompositeAlphaMode::PostMultiplied + } else { + wgpu::CompositeAlphaMode::Auto + } + } + + /// Create a `WindowBuilder` from the configuration given. This window is + /// initially invisible and must later be made visible. + pub(crate) fn to_window(&self) -> WindowBuilder { + // start building the window + let mut builder = WindowBuilder::new() + .with_title(self.title) + .with_visible(false) + .with_inner_size(LogicalSize::new( + self.default_width.get(), + self.default_height.get(), + )); + + match self.mode { + WindowMode::Windowed(window_info) => { + builder = builder.with_maximized(window_info.default_maximized); + + if let Some(resizing_options) = window_info.resizable { + if resizing_options.max_height.is_some() || resizing_options.max_width.is_some() + { + builder = builder.with_max_inner_size(LogicalSize::new( + resizing_options.max_width.unwrap_or(NonZeroU32::MAX).get(), + resizing_options.max_height.unwrap_or(NonZeroU32::MAX).get(), + )); + } + + if resizing_options.min_height.is_some() || resizing_options.min_width.is_some() + { + builder = builder.with_min_inner_size(LogicalSize::new( + resizing_options.min_width.unwrap_or(NonZeroU32::MAX).get(), + resizing_options.min_height.unwrap_or(NonZeroU32::MAX).get(), + )); + } + } else { + builder = builder.with_resizable(false); + } + + // TODO clamp the position to the monitor's size + builder = builder.with_position(LogicalPosition::new( + window_info.default_x, + window_info.default_y, + )); + } + WindowMode::BorderlessFullscreen => { + builder = builder.with_fullscreen(Some(Fullscreen::Borderless(None))); + } + } + + builder + } + + /// Gets a surface configuration out of the config. + pub(crate) fn to_surface_configuration( + &self, + supported_present_modes: &[wgpu::PresentMode], + supported_alpha_modes: &[wgpu::CompositeAlphaMode], + texture_format: wgpu::TextureFormat, + ) -> wgpu::SurfaceConfiguration { + let present_mode = Self::present_mode(self.vsync, supported_present_modes); + let alpha_mode = Self::alpha_mode(supported_alpha_modes); + + // configuration for the surface + wgpu::SurfaceConfiguration { + usage: wgpu::TextureUsages::RENDER_ATTACHMENT, + format: texture_format, + width: self.default_width.get(), + height: self.default_height.get(), + alpha_mode, + present_mode, + } + } + + /// Get the power preference + pub(crate) const fn power_preference(&self) -> wgpu::PowerPreference { + if self.low_power { + wgpu::PowerPreference::LowPower + } else { + wgpu::PowerPreference::HighPerformance + } + } +} -- cgit v1.2.3