Browse Source

Address more comments

Use symmetric left/right top screen types, but keep the public API the
same. Switch const -> static where feasible in the example.
pull/76/head
Ian Chamberlain 2 years ago
parent
commit
7718269b19
No known key found for this signature in database
GPG Key ID: AE5484D09405AA60
  1. 2
      ctru-rs/examples/gfx-3d-mode.rs
  2. 68
      ctru-rs/src/gfx.rs

2
ctru-rs/examples/gfx-3d-mode.rs

@ -7,7 +7,7 @@ use ctru::prelude::*;
/// probably not be viewed for too long or at all if you are photosensitive. /// probably not be viewed for too long or at all if you are photosensitive.
const IMAGE: &[u8] = include_bytes!("assets/ferris.rgb"); const IMAGE: &[u8] = include_bytes!("assets/ferris.rgb");
const ZERO: &[u8] = &[0; IMAGE.len()]; static ZERO: &[u8] = &[0; IMAGE.len()];
fn main() { fn main() {
ctru::init(); ctru::init();

68
ctru-rs/src/gfx.rs

@ -10,11 +10,12 @@ use crate::services::gspgpu::{self, FramebufferFormat};
use crate::services::ServiceReference; use crate::services::ServiceReference;
mod private { mod private {
use super::{BottomScreen, TopScreen, TopScreenRight}; use super::{BottomScreen, TopScreen, TopScreenLeft, TopScreenRight};
pub trait Sealed {} pub trait Sealed {}
impl Sealed for TopScreen {} impl Sealed for TopScreen {}
impl Sealed for TopScreenLeft {}
impl Sealed for TopScreenRight {} impl Sealed for TopScreenRight {}
impl Sealed for BottomScreen {} impl Sealed for BottomScreen {}
} }
@ -60,22 +61,19 @@ pub trait Screen: private::Sealed {
#[non_exhaustive] #[non_exhaustive]
/// The top screen. Mutable access to this struct is required to write to the top /// The top screen. Mutable access to this struct is required to write to the top
/// screen's frame buffer. To enable 3D mode, it can be converted into a [`TopScreen3D`]. /// screen's frame buffer. To enable 3D mode, it can be converted into a [`TopScreen3D`].
pub struct TopScreen; pub struct TopScreen {
left: TopScreenLeft,
right: TopScreenRight,
}
/// A helper container for both sides of the top screen. Once the [`TopScreen`] is /// A helper container for both sides of the top screen. Once the [`TopScreen`] is
/// converted into this, 3D mode will be enabled until this struct is dropped. /// converted into this, 3D mode will be enabled until this struct is dropped.
pub struct TopScreen3D<'top_screen> { pub struct TopScreen3D<'top_screen> {
// morally, this should be &mut or RefMut, but if we do screen: &'top_screen RefCell<TopScreen>,
// - &mut: it means gfx can no longer be borrowed immutably while this exists
// - RefMut: we don't have an easy way to obtain Ref<dyn Screen> for the left side.
// maybe this one isn't as important since the use case is typically RefMut anyway.
// we could just return &dyn Screen instead of Ref<dyn Screen> ?
left: &'top_screen RefCell<TopScreen>,
right: RefCell<TopScreenRight>,
} }
// TODO: it feels a little weird to have an asymmetric separate type like this, struct TopScreenLeft;
// but maybe if it's not `pub` it's not as weird...
struct TopScreenRight; struct TopScreenRight;
#[non_exhaustive] #[non_exhaustive]
@ -132,7 +130,7 @@ impl Gfx {
bottom_fb_fmt: FramebufferFormat, bottom_fb_fmt: FramebufferFormat,
use_vram_buffers: bool, use_vram_buffers: bool,
) -> Result<Self> { ) -> Result<Self> {
let _service_handler = ServiceReference::new( let handler = ServiceReference::new(
&GFX_ACTIVE, &GFX_ACTIVE,
false, false,
|| unsafe { || unsafe {
@ -144,9 +142,9 @@ impl Gfx {
)?; )?;
Ok(Self { Ok(Self {
top_screen: RefCell::new(TopScreen), top_screen: RefCell::new(TopScreen::new()),
bottom_screen: RefCell::new(BottomScreen), bottom_screen: RefCell::new(BottomScreen),
_service_handler, _service_handler: handler,
}) })
} }
@ -203,34 +201,32 @@ impl<'screen> RawFrameBuffer<'screen> {
impl TopScreen3D<'_> { impl TopScreen3D<'_> {
/// Immutably borrow the left side of the screen. /// Immutably borrow the left side of the screen.
pub fn left(&self) -> Ref<dyn Screen> { pub fn left(&self) -> Ref<dyn Screen> {
self.left.borrow() Ref::map(self.screen.borrow(), |screen| &screen.left)
} }
/// Mutably borrow the left side of the screen. /// Mutably borrow the left side of the screen.
pub fn left_mut(&self) -> RefMut<dyn Screen> { pub fn left_mut(&self) -> RefMut<dyn Screen> {
self.left.borrow_mut() RefMut::map(self.screen.borrow_mut(), |screen| &mut screen.left)
} }
/// Immutably borrow the right side of the screen. /// Immutably borrow the right side of the screen.
pub fn right(&self) -> Ref<dyn Screen> { pub fn right(&self) -> Ref<dyn Screen> {
self.right.borrow() Ref::map(self.screen.borrow(), |screen| &screen.right)
} }
/// Mutably borrow the right side of the screen. /// Mutably borrow the right side of the screen.
pub fn right_mut(&self) -> RefMut<dyn Screen> { pub fn right_mut(&self) -> RefMut<dyn Screen> {
self.right.borrow_mut() RefMut::map(self.screen.borrow_mut(), |screen| &mut screen.right)
} }
} }
impl<'a> From<&'a RefCell<TopScreen>> for TopScreen3D<'a> { impl<'top_screen> From<&'top_screen RefCell<TopScreen>> for TopScreen3D<'top_screen> {
fn from(top_screen: &'a RefCell<TopScreen>) -> Self { fn from(top_screen: &'top_screen RefCell<TopScreen>) -> Self {
unsafe { unsafe {
ctru_sys::gfxSet3D(true); ctru_sys::gfxSet3D(true);
} }
TopScreen3D {
left: top_screen, TopScreen3D { screen: top_screen }
right: RefCell::new(TopScreenRight),
}
} }
} }
@ -243,6 +239,13 @@ impl Drop for TopScreen3D<'_> {
} }
impl TopScreen { impl TopScreen {
fn new() -> Self {
Self {
left: TopScreenLeft,
right: TopScreenRight,
}
}
/// Enable or disable wide mode on the top screen. /// Enable or disable wide mode on the top screen.
pub fn set_wide_mode(&mut self, enable: bool) { pub fn set_wide_mode(&mut self, enable: bool) {
unsafe { unsafe {
@ -257,6 +260,16 @@ impl TopScreen {
} }
impl Screen for TopScreen { impl Screen for TopScreen {
fn as_raw(&self) -> ctru_sys::gfxScreen_t {
self.left.as_raw()
}
fn side(&self) -> Side {
self.left.side()
}
}
impl Screen for TopScreenLeft {
fn as_raw(&self) -> ctru_sys::gfxScreen_t { fn as_raw(&self) -> ctru_sys::gfxScreen_t {
ctru_sys::GFX_TOP ctru_sys::GFX_TOP
} }
@ -288,10 +301,9 @@ impl Screen for BottomScreen {
impl From<Side> for ctru_sys::gfx3dSide_t { impl From<Side> for ctru_sys::gfx3dSide_t {
fn from(s: Side) -> ctru_sys::gfx3dSide_t { fn from(s: Side) -> ctru_sys::gfx3dSide_t {
use self::Side::*;
match s { match s {
Left => ctru_sys::GFX_LEFT, Side::Left => ctru_sys::GFX_LEFT,
Right => ctru_sys::GFX_RIGHT, Side::Right => ctru_sys::GFX_RIGHT,
} }
} }
} }
@ -304,6 +316,6 @@ mod tests {
#[test] #[test]
fn gfx_duplicate() { fn gfx_duplicate() {
// We don't need to build a `Gfx` because the test runner has one already // We don't need to build a `Gfx` because the test runner has one already
assert!(matches!(Gfx::init(), Err(Error::ServiceAlreadyActive))) assert!(matches!(Gfx::init(), Err(Error::ServiceAlreadyActive)));
} }
} }

Loading…
Cancel
Save