From 9e06a13c6d7e74667aee2e37481aca07a6c9fd48 Mon Sep 17 00:00:00 2001 From: gered Date: Tue, 7 Mar 2023 17:33:42 -0500 Subject: [PATCH] move vsync and target_framerate options back into System since i realized there is an SDL hint that can be used to toggle this the reason why the rust-sdl "Canvas" struct (which abstracts an "SDL_Renderer") is not being created in System directly (which would allow vsync to be toggled on/off via System directly without the use of a hint) is because not all future SystemResource implementations will need it (e.g. a future OpenGL implementation definitely won't). --- examples/audio_playback/src/main.rs | 7 ++- examples/balls/src/main.rs | 3 +- examples/balls_v2/src/main.rs | 7 ++- examples/slimed/src/main.rs | 7 ++- examples/template_complicated/src/main.rs | 7 ++- examples/template_minimal/src/main.rs | 7 ++- ggdt/src/system/mod.rs | 68 +++++++++++++++-------- ggdt/src/system/res/dos_like.rs | 40 ------------- ggdt/src/system/res/mod.rs | 2 - 9 files changed, 73 insertions(+), 75 deletions(-) diff --git a/examples/audio_playback/src/main.rs b/examples/audio_playback/src/main.rs index b6cd654..09af916 100644 --- a/examples/audio_playback/src/main.rs +++ b/examples/audio_playback/src/main.rs @@ -53,8 +53,11 @@ impl AudioGenerator for SineWaveGenerator { } fn main() -> Result<()> { - let config = DosLikeConfig::new().vsync(true); - let mut system = SystemBuilder::new().window_title("Audio Playback").build(config)?; + let config = DosLikeConfig::new(); + let mut system = SystemBuilder::new() + .window_title("Audio Playback") + .vsync(true) + .build(config)?; let mut using_queue_commands = false; let mut volume = 1.0; diff --git a/examples/balls/src/main.rs b/examples/balls/src/main.rs index 0628a1a..4a05b94 100644 --- a/examples/balls/src/main.rs +++ b/examples/balls/src/main.rs @@ -22,9 +22,10 @@ struct Ball { } fn main() -> Result<()> { - let config = DosLikeConfig::new().vsync(true); + let config = DosLikeConfig::new(); let mut system = SystemBuilder::new() .window_title("Flying Balls!") + .vsync(true) .build(config)?; let font = BitmaskFont::new_vga_font()?; diff --git a/examples/balls_v2/src/main.rs b/examples/balls_v2/src/main.rs index 2c28709..68fb995 100644 --- a/examples/balls_v2/src/main.rs +++ b/examples/balls_v2/src/main.rs @@ -12,8 +12,11 @@ mod entities; mod states; fn main() -> Result<()> { - let config = DosLikeConfig::new().vsync(true); - let system = SystemBuilder::new().window_title("Flying Balls").build(config)?; + let config = DosLikeConfig::new(); + let system = SystemBuilder::new() + .window_title("Flying Balls") + .vsync(true) + .build(config)?; let mut game = Game::new(system)?; let mut states = States::new(); states.push(SimulationState)?; diff --git a/examples/slimed/src/main.rs b/examples/slimed/src/main.rs index d00e873..3746f8f 100644 --- a/examples/slimed/src/main.rs +++ b/examples/slimed/src/main.rs @@ -196,8 +196,11 @@ impl Game { } fn main() -> Result<()> { - let config = DosLikeConfig::new().vsync(true); - let system = SystemBuilder::new().window_title("Slime Stabbing Simulator").build(config)?; + let config = DosLikeConfig::new(); + let system = SystemBuilder::new() + .window_title("Slime Stabbing Simulator") + .vsync(true) + .build(config)?; let game = Game::new(system)?; main_loop(game, MainMenuState::new()).context("Main loop error") } diff --git a/examples/template_complicated/src/main.rs b/examples/template_complicated/src/main.rs index 159934b..92b9387 100644 --- a/examples/template_complicated/src/main.rs +++ b/examples/template_complicated/src/main.rs @@ -225,8 +225,11 @@ impl App { ////////////////////////////////////////////////////////////////////////////////////////////////// fn main() -> Result<()> { - let config = DosLikeConfig::new().vsync(true); - let system = SystemBuilder::new().window_title("Complicated Template").build(config)?; + let config = DosLikeConfig::new(); + let system = SystemBuilder::new() + .window_title("Complicated Template") + .vsync(true) + .build(config)?; let app = App::new(system)?; main_loop(app, DemoState).context("Main loop error") } diff --git a/examples/template_minimal/src/main.rs b/examples/template_minimal/src/main.rs index 11ce3c7..eebffed 100644 --- a/examples/template_minimal/src/main.rs +++ b/examples/template_minimal/src/main.rs @@ -6,8 +6,11 @@ use ggdt::system::*; use ggdt::utils::rnd_value; fn main() -> Result<()> { - let config = DosLikeConfig::new().vsync(true); - let mut system = SystemBuilder::new().window_title("Minimal Template").build(config)?; + let config = DosLikeConfig::new(); + let mut system = SystemBuilder::new() + .window_title("Minimal Template") + .vsync(true) + .build(config)?; system.res.video.clear(0); system.res.video.print_string("Hello, world!", 20, 20, FontRenderOpts::Color(15), &system.res.font); diff --git a/ggdt/src/system/mod.rs b/ggdt/src/system/mod.rs index 8a20e20..ca30123 100644 --- a/ggdt/src/system/mod.rs +++ b/ggdt/src/system/mod.rs @@ -70,6 +70,8 @@ pub enum SystemError { #[derive(Debug)] pub struct SystemBuilder { window_title: String, + vsync: bool, + target_framerate: Option, resizable: bool, show_mouse: bool, relative_mouse_scaling: bool, @@ -81,6 +83,8 @@ impl SystemBuilder { pub fn new() -> SystemBuilder { SystemBuilder { window_title: String::new(), + vsync: false, + target_framerate: None, resizable: true, show_mouse: false, relative_mouse_scaling: true, @@ -89,13 +93,30 @@ impl SystemBuilder { } /// Set the window title for the [`System`] to be built. - pub fn window_title(&mut self, window_title: &str) -> &mut SystemBuilder { + pub fn window_title(mut self, window_title: &str) -> Self { self.window_title = window_title.to_string(); self } + /// Enables or disables V-Sync for the [`System`] to be built. Enabling V-sync automatically + /// disables `target_framerate`. + pub fn vsync(mut self, enable: bool) -> Self { + self.vsync = enable; + self.target_framerate = None; + self + } + + /// Sets a target framerate for the [`System`] being built to run at. This is intended to be + /// used when V-sync is not desired, so setting a target framerate automatically disables + /// `vsync`. + pub fn target_framerate(mut self, target_framerate: u32) -> Self { + self.target_framerate = Some(target_framerate); + self.vsync = false; + self + } + /// Sets whether the window will be resizable by the user for the [`System`] being built. - pub fn resizable(&mut self, enable: bool) -> &mut SystemBuilder { + pub fn resizable(mut self, enable: bool) -> Self { self.resizable = enable; self } @@ -103,14 +124,14 @@ impl SystemBuilder { /// Enables or disables mouse cursor display by the operating system when the cursor is over /// the window for the [`System`] being built. Disable this if you intend to render your own /// custom mouse cursor. - pub fn show_mouse(&mut self, enable: bool) -> &mut SystemBuilder { + pub fn show_mouse(mut self, enable: bool) -> Self { self.show_mouse = enable; self } /// Enables or disables automatic DPI scaling of mouse relative movement values (delta values) /// available via the [`Mouse`] input device. - pub fn relative_mouse_scaling(&mut self, enable: bool) -> &mut SystemBuilder { + pub fn relative_mouse_scaling(mut self, enable: bool) -> Self { self.relative_mouse_scaling = enable; self } @@ -120,7 +141,7 @@ impl SystemBuilder { /// default setting that [`SystemBuilder`] configures is to follow the SDL default, except where /// the setting affects the system globally (in certain desktop environments, e.g. KDE/Kwin) /// which may be undesired by end-users, at the cost of some additional input latency. - pub fn skip_x11_compositor(&mut self, enable: bool) -> &mut SystemBuilder { + pub fn skip_x11_compositor(mut self, enable: bool) -> Self { self.skip_x11_compositor = enable; self } @@ -130,23 +151,10 @@ impl SystemBuilder { &self, config: ConfigType, ) -> Result, SystemError> { - sdl2::hint::set( - "SDL_MOUSE_RELATIVE_SCALING", - if self.relative_mouse_scaling { - "1" - } else { - "0" - }, - ); - sdl2::hint::set( - "SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR", - if self.skip_x11_compositor { - "1" - } else { - "0" - }, - ); + sdl2::hint::set("SDL_RENDER_VSYNC", if self.vsync { "1" } else { "0" }); + sdl2::hint::set("SDL_MOUSE_RELATIVE_SCALING", if self.relative_mouse_scaling { "1" } else { "0" }); + sdl2::hint::set("SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR", if self.skip_x11_compositor { "1" } else { "0" }); // build all the individual SDL subsystems @@ -211,6 +219,8 @@ impl SystemBuilder { sdl_timer_subsystem, res: system_resources, event_pump, + vsync: self.vsync, + target_framerate: self.target_framerate, target_framerate_delta: None, next_tick: 0, }) @@ -228,6 +238,8 @@ where SystemResType: SystemResources { sdl_video_subsystem: VideoSubsystem, sdl_timer_subsystem: TimerSubsystem, + vsync: bool, + target_framerate: Option, target_framerate_delta: Option, next_tick: i64, @@ -241,6 +253,8 @@ where SystemResType: SystemResources { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("System") .field("res", &self.res) + .field("vsync", &self.vsync) + .field("target_framerate", &self.target_framerate) .field("target_framerate_delta", &self.target_framerate_delta) .field("next_tick", &self.next_tick) .finish_non_exhaustive() @@ -259,7 +273,7 @@ where SystemResType: SystemResources { // if a specific target framerate is desired, apply some loop timing/delay to achieve it // TODO: do this better. delaying when running faster like this is a poor way to do this.. - if let Some(target_framerate) = self.res.target_framerate() { + if let Some(target_framerate) = self.target_framerate { if self.target_framerate_delta.is_some() { // normal path for every other loop iteration except the first let delay = self.next_tick - self.ticks() as i64; @@ -346,6 +360,16 @@ where SystemResType: SystemResources { Ok(()) } + #[inline] + pub fn vsync(&self) -> bool { + self.vsync + } + + #[inline] + pub fn target_framerate(&self) -> Option { + self.target_framerate + } + pub fn ticks(&self) -> u64 { self.sdl_timer_subsystem.performance_counter() } diff --git a/ggdt/src/system/res/dos_like.rs b/ggdt/src/system/res/dos_like.rs index 3e95c9d..4e73b94 100644 --- a/ggdt/src/system/res/dos_like.rs +++ b/ggdt/src/system/res/dos_like.rs @@ -5,8 +5,6 @@ use crate::system::*; pub struct DosLikeConfig { screen_width: u32, screen_height: u32, - vsync: bool, - target_framerate: Option, initial_scale_factor: u32, integer_scaling: bool, } @@ -16,30 +14,11 @@ impl DosLikeConfig { DosLikeConfig { screen_width: SCREEN_WIDTH, screen_height: SCREEN_HEIGHT, - vsync: false, - target_framerate: None, initial_scale_factor: DEFAULT_SCALE_FACTOR, integer_scaling: false, } } - /// Enables or disables V-Sync for the [`System`] to be built. Enabling V-sync automatically - /// disables `target_framerate`. - pub fn vsync(mut self, enable: bool) -> Self { - self.vsync = enable; - self.target_framerate = None; - self - } - - /// Sets a target framerate for the [`System`] being built to run at. This is intended to be - /// used when V-sync is not desired, so setting a target framerate automatically disables - /// `vsync`. - pub fn target_framerate(mut self, target_framerate: u32) -> Self { - self.target_framerate = Some(target_framerate); - self.vsync = false; - self - } - /// Sets an integer scaling factor for the [`System`] being built to up-scale the virtual /// framebuffer to when displaying it on screen. pub fn scale_factor(mut self, scale_factor: u32) -> Self { @@ -75,9 +54,6 @@ impl SystemResourcesConfig for DosLikeConfig { // turn the window into a canvas (under the hood, an SDL Renderer that owns the window) let mut canvas_builder = window.into_canvas(); - if self.vsync { - canvas_builder = canvas_builder.present_vsync(); - } let mut sdl_canvas = match canvas_builder.build() { Ok(canvas) => canvas, Err(error) => return Err(SystemResourcesError::SDLError(error.to_string())), @@ -162,8 +138,6 @@ impl SystemResourcesConfig for DosLikeConfig { sdl_texture, sdl_texture_pitch, texture_pixels, - vsync: self.vsync, - target_framerate: self.target_framerate, audio, audio_queue, palette, @@ -180,8 +154,6 @@ pub struct DosLike { sdl_texture: Texture, sdl_texture_pitch: usize, texture_pixels: Box<[u32]>, - vsync: bool, - target_framerate: Option, /// An [`Audio`] instance that allows interacting with the system's audio output device. pub audio: Audio, @@ -223,8 +195,6 @@ impl std::fmt::Debug for DosLike { .field("font", &self.font) .field("keyboard", &self.keyboard) .field("mouse", &self.mouse) - .field("vsync", &self.vsync) - .field("target_framerate", &self.target_framerate) .finish_non_exhaustive() } } @@ -285,14 +255,4 @@ impl SystemResources for DosLike { fn height(&self) -> u32 { self.video.height() } - - #[inline] - fn vsync(&self) -> bool { - self.vsync - } - - #[inline] - fn target_framerate(&self) -> Option { - self.target_framerate - } } diff --git a/ggdt/src/system/res/mod.rs b/ggdt/src/system/res/mod.rs index ccf2ba9..96e1245 100644 --- a/ggdt/src/system/res/mod.rs +++ b/ggdt/src/system/res/mod.rs @@ -36,6 +36,4 @@ pub trait SystemResources : std::fmt::Debug { fn width(&self) -> u32; fn height(&self) -> u32; - fn vsync(&self) -> bool; - fn target_framerate(&self) -> Option; }