summaryrefslogtreecommitdiff
path: root/src/renderer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/renderer.rs')
-rw-r--r--src/renderer.rs169
1 files changed, 16 insertions, 153 deletions
diff --git a/src/renderer.rs b/src/renderer.rs
index c9c51bc..bf7226d 100644
--- a/src/renderer.rs
+++ b/src/renderer.rs
@@ -1,13 +1,12 @@
-use std::{borrow::Cow, num::NonZeroU32};
-
+use crate::config::RenderWindowConfig;
use pollster::FutureExt;
use thiserror::Error;
use winit::{
- dpi::{LogicalPosition, LogicalSize, PhysicalSize},
+ dpi::PhysicalSize,
error::OsError,
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
- window::{Fullscreen, Window, WindowBuilder},
+ window::Window,
};
/// No device could be found which supports the given surface
@@ -33,83 +32,6 @@ pub enum NewRendererError {
WindowInitError(#[from] OsError),
}
-/// Describes how a window may be resized
-#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
-pub struct Resizable {
- /// The minimum width of the window, or None if unconstrained
- pub min_width: Option<NonZeroU32>,
- /// The minimum height of the window, or None if unconstrained
- pub min_height: Option<NonZeroU32>,
- /// The maximum width of the window, or None if unconstrained
- pub max_width: Option<NonZeroU32>,
- /// The maximum height of the window, or None if unconstrained
- pub max_height: Option<NonZeroU32>,
-}
-
-/// Information about a window, that is not fullscreened
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub struct WindowInfo {
- pub default_x: i32,
- pub default_y: i32,
- pub resizable: Option<Resizable>,
- 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)]
-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)]
-// 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: Cow<'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,
-}
-
-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".into(),
- low_power: true,
- vsync: true,
- }
- }
-}
-
pub struct Renderer {
surface: wgpu::Surface,
device: wgpu::Device,
@@ -126,57 +48,19 @@ impl Renderer {
///
/// Returns a [`NoGpu`] error if no device could be detected that can
/// display to the window
+ ///
+ /// # Panics
+ ///
+ /// This function **must** be called on the main thread, or else it may
+ /// panic on some platforms.
// TODO make it possible to use without a window (ie, use a bitmap in memory as a surface)
// TODO this function needs to be smaller
- #[allow(clippy::missing_panics_doc)]
pub fn new(
- config: RenderWindowConfig,
+ config: &RenderWindowConfig,
event_loop: &EventLoop<()>,
) -> Result<Self, NewRendererError> {
- // start building the window
- let mut builder = WindowBuilder::new()
- .with_title(config.title)
- .with_inner_size(LogicalSize::new(
- config.default_width.get(),
- config.default_height.get(),
- ));
-
- match config.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)));
- }
- }
-
- let window = builder.build(event_loop)?;
+ // build the window
+ let window = config.to_window().build(event_loop)?;
// the instance's main purpose is to create an adapter and a surface
let instance = wgpu::Instance::new(wgpu::Backends::all());
@@ -184,11 +68,7 @@ impl Renderer {
// the surface is the part of the screen we'll draw to
let surface = unsafe { instance.create_surface(&window) };
- let power_preference = if config.low_power {
- wgpu::PowerPreference::LowPower
- } else {
- wgpu::PowerPreference::HighPerformance
- };
+ let power_preference = config.power_preference();
// the adapter is the handle to the GPU
let adapter = instance
@@ -219,28 +99,11 @@ impl Renderer {
.block_on()
.unwrap();
- let present_mode = if config.vsync {
- wgpu::PresentMode::Fifo
- } else {
- let modes = surface.get_supported_modes(&adapter);
-
- if modes.contains(&wgpu::PresentMode::Mailbox) {
- wgpu::PresentMode::Mailbox
- } else if modes.contains(&wgpu::PresentMode::Immediate) {
- wgpu::PresentMode::Immediate
- } else {
- wgpu::PresentMode::Fifo
- }
- };
-
// configuration for the surface
- let config = wgpu::SurfaceConfiguration {
- usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
- format: surface.get_supported_formats(&adapter)[0],
- width: config.default_width.get(),
- height: config.default_height.get(),
- present_mode,
- };
+ let config = config.to_surface_configuration(
+ &surface.get_supported_modes(&adapter),
+ surface.get_supported_formats(&adapter)[0],
+ );
surface.configure(&device, &config);