Browse Source

Separate screens and internal mutability for Gfx

pull/22/head
Andrea Ciliberti 3 years ago
parent
commit
45bf4b5ec7
  1. 17
      ctru-rs/src/console.rs
  2. 103
      ctru-rs/src/gfx.rs

17
ctru-rs/src/console.rs

@ -1,27 +1,30 @@
use std::cell::Ref;
use std::default::Default; use std::default::Default;
use std::marker::PhantomData; use std::marker::PhantomData;
use ctru_sys::{consoleClear, consoleInit, consoleSelect, consoleSetWindow, PrintConsole}; use ctru_sys::{consoleClear, consoleInit, consoleSelect, consoleSetWindow, PrintConsole};
use crate::gfx::{Gfx, Screen}; use crate::gfx::Screen;
pub struct Console<'gfx> { pub struct Console<'screen> {
context: Box<PrintConsole>, context: Box<PrintConsole>,
_gfx: PhantomData<&'gfx ()>, _screen: PhantomData<&'screen ()>,
} }
impl<'gfx> Console<'gfx> { impl<'screen> Console<'screen> {
/// Initialize a console on the chosen screen, overwriting whatever was on the 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 /// previously (including other consoles). The new console is automatically selected for
/// printing. /// printing.
pub fn init(_gfx: &'gfx Gfx, screen: Screen) -> Self { pub fn init(screen: Ref<'screen, Screen>) -> Self {
let mut context = Box::new(PrintConsole::default()); let mut context = Box::new(PrintConsole::default());
unsafe { consoleInit(screen.into(), context.as_mut()) }; let screen_kind = *screen;
unsafe { consoleInit(screen_kind.into(), context.as_mut()) };
Console { Console {
context, context,
_gfx: PhantomData, _screen: PhantomData,
} }
} }

103
ctru-rs/src/gfx.rs

@ -1,5 +1,6 @@
//! LCD screens manipulation helper //! LCD screens manipulation helper
use std::cell::{BorrowError, BorrowMutError, Ref, RefCell, RefMut};
use std::default::Default; use std::default::Default;
use std::ops::Drop; use std::ops::Drop;
@ -9,7 +10,10 @@ use crate::services::gspgpu::{self, FramebufferFormat};
/// provides helper functions and utilities for software rendering. /// provides helper functions and utilities for software rendering.
/// ///
/// The service exits when this struct is dropped. /// The service exits when this struct is dropped.
pub struct Gfx(()); pub struct Gfx {
top_screen: RefCell<Screen>,
bottom_screen: RefCell<Screen>,
}
/// Available screens on the 3DS /// Available screens on the 3DS
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
@ -44,32 +48,30 @@ impl Gfx {
unsafe { unsafe {
ctru_sys::gfxInit(top_fb_fmt.into(), bottom_fb_fmt.into(), use_vram_buffers); ctru_sys::gfxInit(top_fb_fmt.into(), bottom_fb_fmt.into(), use_vram_buffers);
} }
Gfx(()) Gfx {
top_screen: RefCell::new(Screen::Top),
bottom_screen: RefCell::new(Screen::Bottom),
}
} }
/// Enable or disable the 3D stereoscopic effect /// Try to get an immutable reference to the Top screen
pub fn set_3d_enabled(&mut self, enabled: bool) { pub fn get_top_screen(&self) -> Result<Ref<'_, Screen>, BorrowError> {
unsafe { ctru_sys::gfxSet3D(enabled) } self.top_screen.try_borrow()
} }
/// Enable or disable the wide screen mode (top screen). /// Try to get a mutable reference to the Top screen
/// pub fn get_top_screen_mut(&self) -> Result<RefMut<'_, Screen>, BorrowMutError> {
/// This only works when 3D is disabled. self.top_screen.try_borrow_mut()
pub fn set_wide_mode(&mut self, enabled: bool) {
unsafe { ctru_sys::gfxSetWide(enabled) };
} }
/// Get the status of wide screen mode. /// Try to get an immutable reference to the Bottom screen
pub fn get_wide_mode(&self) -> bool { pub fn get_bottom_screen(&self) -> Result<Ref<'_, Screen>, BorrowError> {
unsafe { ctru_sys::gfxIsWide() } self.bottom_screen.try_borrow()
} }
/// Sets whether to use double buffering. Enabled by default. /// Try to get a mutable reference to the Bottom screen
/// pub fn get_bottom_screen_mut(&self) -> Result<RefMut<'_, Screen>, BorrowMutError> {
/// Note that even when double buffering is disabled, one should still use the `swap_buffers` self.bottom_screen.try_borrow_mut()
/// 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) }
} }
/// Flushes the current framebuffers /// Flushes the current framebuffers
@ -97,13 +99,63 @@ impl Gfx {
pub fn wait_for_vblank(&self) { pub fn wait_for_vblank(&self) {
gspgpu::wait_for_event(gspgpu::Event::VBlank0, true); gspgpu::wait_for_event(gspgpu::Event::VBlank0, true);
} }
}
impl Screen {
/// 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()),
}
}
/// Gets the framebuffer format for a screen /// 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()),
}
}
/// Get the status of wide screen mode.
///
/// #Errors
/// When called by the Bottom screen
pub fn get_wide_mode(&self) -> Result<bool, String> {
match self {
Screen::Top => unsafe { Ok(ctru_sys::gfxIsWide()) },
Screen::Bottom => Err("Tried to check wide-mode status on bottom screen".to_string()),
}
}
/// 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) }
}
/// Gets the framebuffer format
pub fn get_framebuffer_format(&self, screen: Screen) -> FramebufferFormat { pub fn get_framebuffer_format(&self, screen: Screen) -> FramebufferFormat {
unsafe { ctru_sys::gfxGetScreenFormat(screen.into()).into() } unsafe { ctru_sys::gfxGetScreenFormat(screen.into()).into() }
} }
/// Change the framebuffer format for a screen /// Change the framebuffer format
pub fn set_framebuffer_format(&mut self, screen: Screen, fmt: FramebufferFormat) { pub fn set_framebuffer_format(&mut self, screen: Screen, fmt: FramebufferFormat) {
unsafe { ctru_sys::gfxSetScreenFormat(screen.into(), fmt.into()) } unsafe { ctru_sys::gfxSetScreenFormat(screen.into(), fmt.into()) }
} }
@ -114,14 +166,16 @@ impl Gfx {
/// ///
/// Note that the pointer returned by this function can change after each call to this function /// Note that the pointer returned by this function can change after each call to this function
/// if double buffering is enabled /// if double buffering is enabled
pub unsafe fn get_raw_framebuffer(&self, screen: Screen, side: Side) -> (*mut u8, u16, u16) { pub fn get_raw_framebuffer(&self, screen: Screen, side: Side) -> (*mut u8, u16, u16) {
let mut width: u16 = 0; let mut width: u16 = 0;
let mut height: u16 = 0; let mut height: u16 = 0;
unsafe {
let buf: *mut u8 = let buf: *mut u8 =
ctru_sys::gfxGetFramebuffer(screen.into(), side.into(), &mut width, &mut height); ctru_sys::gfxGetFramebuffer(screen.into(), side.into(), &mut width, &mut height);
(buf, width, height) (buf, width, height)
} }
} }
}
impl From<Screen> for ctru_sys::gfxScreen_t { impl From<Screen> for ctru_sys::gfxScreen_t {
fn from(g: Screen) -> ctru_sys::gfxScreen_t { fn from(g: Screen) -> ctru_sys::gfxScreen_t {
@ -146,7 +200,10 @@ impl From<Side> for ctru_sys::gfx3dSide_t {
impl Default for Gfx { impl Default for Gfx {
fn default() -> Self { fn default() -> Self {
unsafe { ctru_sys::gfxInitDefault() }; unsafe { ctru_sys::gfxInitDefault() };
Gfx(()) Gfx {
top_screen: RefCell::new(Screen::Top),
bottom_screen: RefCell::new(Screen::Bottom),
}
} }
} }

Loading…
Cancel
Save