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).
This commit is contained in:
Gered 2023-03-07 17:33:42 -05:00
parent 29628bf680
commit 9e06a13c6d
9 changed files with 73 additions and 75 deletions

View file

@ -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;

View file

@ -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()?;

View file

@ -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)?;

View file

@ -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")
}

View file

@ -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")
}

View file

@ -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);

View file

@ -70,6 +70,8 @@ pub enum SystemError {
#[derive(Debug)]
pub struct SystemBuilder {
window_title: String,
vsync: bool,
target_framerate: Option<u32>,
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<System<ConfigType::SystemResourcesType>, 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<u32>,
target_framerate_delta: Option<i64>,
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<u32> {
self.target_framerate
}
pub fn ticks(&self) -> u64 {
self.sdl_timer_subsystem.performance_counter()
}

View file

@ -5,8 +5,6 @@ use crate::system::*;
pub struct DosLikeConfig {
screen_width: u32,
screen_height: u32,
vsync: bool,
target_framerate: Option<u32>,
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<u32>,
/// 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<u32> {
self.target_framerate
}
}

View file

@ -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<u32>;
}