From 53aa05a00331204706f53862ac1790c7b1dc1a68 Mon Sep 17 00:00:00 2001 From: Andrea Ciliberti Date: Tue, 18 Jan 2022 14:27:56 +0100 Subject: [PATCH] Split Screen enum into structs and trait --- ctru-rs/src/console.rs | 6 +- ctru-rs/src/gfx.rs | 166 +++++++++++++++++++++++------------------ 2 files changed, 95 insertions(+), 77 deletions(-) diff --git a/ctru-rs/src/console.rs b/ctru-rs/src/console.rs index f5e2114..178e006 100644 --- a/ctru-rs/src/console.rs +++ b/ctru-rs/src/console.rs @@ -15,12 +15,10 @@ impl<'screen> Console<'screen> { /// Initialize a console on the chosen screen, overwriting whatever was on the screen /// previously (including other consoles). The new console is automatically selected for /// printing. - pub fn init(screen: Ref<'screen, Screen>) -> Self { + pub fn init(screen: Ref<'screen, impl Screen>) -> Self { let mut context = Box::new(PrintConsole::default()); - let screen_kind = *screen; - - unsafe { consoleInit(screen_kind.into(), context.as_mut()) }; + unsafe { consoleInit(screen.into_raw(), context.as_mut()) }; Console { context, diff --git a/ctru-rs/src/gfx.rs b/ctru-rs/src/gfx.rs index 13be457..0473bb3 100644 --- a/ctru-rs/src/gfx.rs +++ b/ctru-rs/src/gfx.rs @@ -11,19 +11,39 @@ use crate::services::gspgpu::{self, FramebufferFormat}; /// /// The service exits when this struct is dropped. pub struct Gfx { - top_screen: RefCell, - bottom_screen: RefCell, + top_screen: RefCell, + bottom_screen: RefCell, } -/// Available screens on the 3DS -#[derive(Copy, Clone, Debug)] -pub enum Screen { - /// The top screen - Top, - /// The bottom screen - Bottom, +/// Trait implemented by TopScreen and BottomScreen for common methods +pub trait Screen { + /// Returns the libctru value for the Screen kind + fn into_raw(&self) -> ctru_sys::gfxScreen_t; + + /// Sets whether to use double buffering. Enabled by default. + /// + /// Note that even when double buffering is disabled, one should still use the `swap_buffers` + /// method on each frame to keep the gsp configuration up to date + fn set_double_buffering(&mut self, enabled: bool); + + /// Gets the framebuffer format + fn get_framebuffer_format(&self) -> FramebufferFormat; + + /// Change the framebuffer format + fn set_framebuffer_format(&mut self, fmt: FramebufferFormat); + + /// Returns a tuple containing a pointer to the specifified framebuffer (as determined by the + /// calling screen and `Side`), the width of the framebuffer in pixels, and the height of + /// the framebuffer in pixels + /// + /// Note that the pointer returned by this function can change after each call to this function + /// if double buffering is enabled + fn get_raw_framebuffer(&self, side: Side) -> (*mut u8, u16, u16); } +pub struct TopScreen; +pub struct BottomScreen; + #[derive(Copy, Clone, Debug)] /// Side of top screen framebuffer /// @@ -49,28 +69,28 @@ impl Gfx { ctru_sys::gfxInit(top_fb_fmt.into(), bottom_fb_fmt.into(), use_vram_buffers); } Gfx { - top_screen: RefCell::new(Screen::Top), - bottom_screen: RefCell::new(Screen::Bottom), + top_screen: RefCell::new(TopScreen), + bottom_screen: RefCell::new(BottomScreen), } } /// Try to get an immutable reference to the Top screen - pub fn get_top_screen(&self) -> Result, BorrowError> { + pub fn get_top_screen(&self) -> Result, BorrowError> { self.top_screen.try_borrow() } /// Try to get a mutable reference to the Top screen - pub fn get_top_screen_mut(&self) -> Result, BorrowMutError> { + pub fn get_top_screen_mut(&self) -> Result, BorrowMutError> { self.top_screen.try_borrow_mut() } /// Try to get an immutable reference to the Bottom screen - pub fn get_bottom_screen(&self) -> Result, BorrowError> { + pub fn get_bottom_screen(&self) -> Result, BorrowError> { self.bottom_screen.try_borrow() } /// Try to get a mutable reference to the Bottom screen - pub fn get_bottom_screen_mut(&self) -> Result, BorrowMutError> { + pub fn get_bottom_screen_mut(&self) -> Result, BorrowMutError> { self.bottom_screen.try_borrow_mut() } @@ -101,88 +121,88 @@ impl Gfx { } } -impl Screen { +impl TopScreen { /// Enable or disable the 3D stereoscopic effect - /// - /// #Errors - /// When called by the Bottom screen - pub fn set_3d_enabled(&mut self, enabled: bool) -> Result<(), String> { - match self { - Screen::Top => unsafe { - ctru_sys::gfxSet3D(enabled); - Ok(()) - }, - Screen::Bottom => Err("Tried to enable 3D on bottom screen".to_string()), + pub fn set_3d_enabled(&mut self, enabled: bool) { + unsafe { + ctru_sys::gfxSet3D(enabled); } } /// Enable or disable the wide screen mode (top screen). /// This only works when 3D is disabled. - /// - /// #Errors - /// When called by the Bottom screen - pub fn set_wide_mode(&mut self, enabled: bool) -> Result<(), String> { - match self { - Screen::Top => unsafe { - ctru_sys::gfxSetWide(enabled); - Ok(()) - }, - Screen::Bottom => Err("Tried to change wide-mode on bottom screen".to_string()), + pub fn set_wide_mode(&mut self, enabled: bool) { + unsafe { + ctru_sys::gfxSetWide(enabled); } } /// Get the status of wide screen mode. - /// - /// #Errors - /// When called by the Bottom screen - pub fn get_wide_mode(&self) -> Result { - match self { - Screen::Top => unsafe { Ok(ctru_sys::gfxIsWide()) }, - Screen::Bottom => Err("Tried to check wide-mode status on bottom screen".to_string()), - } + pub fn get_wide_mode(&self) -> bool { + unsafe { ctru_sys::gfxIsWide() } } +} - /// Sets whether to use double buffering. Enabled by default. - /// - /// Note that even when double buffering is disabled, one should still use the `swap_buffers` - /// method on each frame to keep the gsp configuration up to date - pub fn set_double_buffering(&mut self, screen: Screen, enabled: bool) { - unsafe { ctru_sys::gfxSetDoubleBuffering(screen.into(), enabled) } +impl Screen for TopScreen { + fn into_raw(&self) -> ctru_sys::gfxScreen_t { + ctru_sys::GFX_TOP } - /// Gets the framebuffer format - pub fn get_framebuffer_format(&self, screen: Screen) -> FramebufferFormat { - unsafe { ctru_sys::gfxGetScreenFormat(screen.into()).into() } + fn set_double_buffering(&mut self, enabled: bool) { + unsafe { ctru_sys::gfxSetDoubleBuffering(ctru_sys::GFX_TOP, enabled) } } - /// Change the framebuffer format - pub fn set_framebuffer_format(&mut self, screen: Screen, fmt: FramebufferFormat) { - unsafe { ctru_sys::gfxSetScreenFormat(screen.into(), fmt.into()) } + fn get_framebuffer_format(&self) -> FramebufferFormat { + unsafe { ctru_sys::gfxGetScreenFormat(ctru_sys::GFX_TOP).into() } } - /// Returns a tuple containing a pointer to the specifified framebuffer (as determined by the - /// provided `Screen` and `Side`), the width of the framebuffer in pixels, and the height of - /// the framebuffer in pixels - /// - /// Note that the pointer returned by this function can change after each call to this function - /// if double buffering is enabled - pub fn get_raw_framebuffer(&self, screen: Screen, side: Side) -> (*mut u8, u16, u16) { + fn set_framebuffer_format(&mut self, fmt: FramebufferFormat) { + unsafe { ctru_sys::gfxSetScreenFormat(ctru_sys::GFX_TOP, fmt.into()) } + } + + fn get_raw_framebuffer(&self, side: Side) -> (*mut u8, u16, u16) { let mut width: u16 = 0; let mut height: u16 = 0; unsafe { - let buf: *mut u8 = - ctru_sys::gfxGetFramebuffer(screen.into(), side.into(), &mut width, &mut height); + let buf: *mut u8 = ctru_sys::gfxGetFramebuffer( + ctru_sys::GFX_TOP, + side.into(), + &mut width, + &mut height, + ); (buf, width, height) } } } -impl From for ctru_sys::gfxScreen_t { - fn from(g: Screen) -> ctru_sys::gfxScreen_t { - use self::Screen::*; - match g { - Top => ctru_sys::GFX_TOP, - Bottom => ctru_sys::GFX_BOTTOM, +impl Screen for BottomScreen { + fn into_raw(&self) -> ctru_sys::gfxScreen_t { + ctru_sys::GFX_BOTTOM + } + + fn set_double_buffering(&mut self, enabled: bool) { + unsafe { ctru_sys::gfxSetDoubleBuffering(ctru_sys::GFX_BOTTOM, enabled) } + } + + fn get_framebuffer_format(&self) -> FramebufferFormat { + unsafe { ctru_sys::gfxGetScreenFormat(ctru_sys::GFX_BOTTOM).into() } + } + + fn set_framebuffer_format(&mut self, fmt: FramebufferFormat) { + unsafe { ctru_sys::gfxSetScreenFormat(ctru_sys::GFX_BOTTOM, fmt.into()) } + } + + fn get_raw_framebuffer(&self, side: Side) -> (*mut u8, u16, u16) { + let mut width: u16 = 0; + let mut height: u16 = 0; + unsafe { + let buf: *mut u8 = ctru_sys::gfxGetFramebuffer( + ctru_sys::GFX_BOTTOM, + side.into(), + &mut width, + &mut height, + ); + (buf, width, height) } } } @@ -201,8 +221,8 @@ impl Default for Gfx { fn default() -> Self { unsafe { ctru_sys::gfxInitDefault() }; Gfx { - top_screen: RefCell::new(Screen::Top), - bottom_screen: RefCell::new(Screen::Bottom), + top_screen: RefCell::new(TopScreen), + bottom_screen: RefCell::new(BottomScreen), } } }