diff --git a/ctru-rs/examples/gfx-3d-mode.rs b/ctru-rs/examples/gfx-3d-mode.rs index bd678a2..df0593f 100644 --- a/ctru-rs/examples/gfx-3d-mode.rs +++ b/ctru-rs/examples/gfx-3d-mode.rs @@ -1,4 +1,4 @@ -use ctru::gfx::TopScreen3D; +use ctru::gfx::{Screen, Side, TopScreen3D}; use ctru::prelude::*; /// See `graphics-bitmap.rs` for details on how the image is generated. @@ -16,24 +16,14 @@ fn main() { let apt = Apt::init().expect("Couldn't obtain APT controller"); let _console = Console::init(gfx.bottom_screen.borrow_mut()); - println!("Press Start to exit.\nPress A to switch which side is drawn to."); + println!("Press Start to exit.\nPress A to switch sides (be sure to have 3D mode enabled)."); - let top_screen = TopScreen3D::from(&gfx.top_screen); - - // TODO set double buffering for top screen - - let mut left = top_screen.left_mut(); - let left_buf = left.get_raw_framebuffer(); - let mut right = top_screen.right_mut(); - let right_buf = right.get_raw_framebuffer(); + gfx.top_screen.borrow_mut().set_double_buffering(true); - // We assume the image is the correct size already, so we ignore width + height. - let mut buf = left_buf.ptr; + let top_screen = TopScreen3D::from(&gfx.top_screen); + let (mut left, mut right) = top_screen.split_mut(); - // Copy the image into the left-side frame buffer - unsafe { - buf.copy_from(IMAGE.as_ptr(), IMAGE.len()); - } + let mut current_side = Side::Left; // Main loop while apt.main_loop() { @@ -44,22 +34,30 @@ fn main() { break; } + let left_buf = left.get_raw_framebuffer(); + let right_buf = right.get_raw_framebuffer(); + + // Clear both buffers every time, in case the user switches sides this loop + unsafe { + left_buf.ptr.copy_from(ZERO.as_ptr(), ZERO.len()); + right_buf.ptr.copy_from(ZERO.as_ptr(), ZERO.len()); + } + if hid.keys_down().contains(KeyPad::KEY_A) { - // Clear the side we just drew to by zeroing it out - unsafe { - buf.copy_from(ZERO.as_ptr(), ZERO.len()); - } - - // flip which buffer we're writing to, and redraw the image - buf = if buf == left_buf.ptr { - right_buf.ptr - } else { - left_buf.ptr + // flip which buffer we're writing to + current_side = match current_side { + Side::Left => Side::Right, + Side::Right => Side::Left, }; + } + + let buf = match current_side { + Side::Left => left_buf.ptr, + Side::Right => right_buf.ptr, + }; - unsafe { - buf.copy_from(IMAGE.as_ptr(), IMAGE.len()); - } + unsafe { + buf.copy_from(IMAGE.as_ptr(), IMAGE.len()); } // Flush and swap framebuffers diff --git a/ctru-rs/src/gfx.rs b/ctru-rs/src/gfx.rs index 05cb7c9..2e83832 100644 --- a/ctru-rs/src/gfx.rs +++ b/ctru-rs/src/gfx.rs @@ -35,8 +35,17 @@ pub trait Screen: private::Sealed { /// Note that the pointer of the framebuffer returned by this function can /// change after each call to this function if double buffering is enabled. fn get_raw_framebuffer(&mut self) -> RawFrameBuffer { - let side = self.side(); - RawFrameBuffer::for_screen_side(self, side) + let mut width = 0; + let mut height = 0; + let ptr = unsafe { + ctru_sys::gfxGetFramebuffer(self.as_raw(), self.side().into(), &mut width, &mut height) + }; + RawFrameBuffer { + ptr, + width, + height, + screen: PhantomData, + } } /// Sets whether to use double buffering. Enabled by default. @@ -58,7 +67,6 @@ pub trait Screen: private::Sealed { } } -#[non_exhaustive] /// 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`]. pub struct TopScreen { @@ -182,41 +190,19 @@ impl Gfx { } } -impl<'screen> RawFrameBuffer<'screen> { - fn for_screen_side(screen: &'screen mut (impl Screen + ?Sized), side: Side) -> Self { - let mut width = 0; - let mut height = 0; - let ptr = unsafe { - ctru_sys::gfxGetFramebuffer(screen.as_raw(), side.into(), &mut width, &mut height) - }; - Self { - ptr, - width, - height, - screen: PhantomData, - } - } -} - impl TopScreen3D<'_> { - /// Immutably borrow the left side of the screen. - pub fn left(&self) -> Ref { - Ref::map(self.screen.borrow(), |screen| &screen.left) - } - - /// Mutably borrow the left side of the screen. - pub fn left_mut(&self) -> RefMut { - RefMut::map(self.screen.borrow_mut(), |screen| &mut screen.left) - } - - /// Immutably borrow the right side of the screen. - pub fn right(&self) -> Ref { - Ref::map(self.screen.borrow(), |screen| &screen.right) + /// Immutably borrow the two sides of the screen as `(left, right)`. + pub fn split(&self) -> (Ref, Ref) { + Ref::map_split(self.screen.borrow(), |screen| { + (&screen.left as _, &screen.right as _) + }) } - /// Mutably borrow the right side of the screen. - pub fn right_mut(&self) -> RefMut { - RefMut::map(self.screen.borrow_mut(), |screen| &mut screen.right) + /// Mutably borrow the two sides of the screen as `(left, right)`. + pub fn split_mut(&self) -> (RefMut, RefMut) { + RefMut::map_split(self.screen.borrow_mut(), |screen| { + (&mut screen.left as _, &mut screen.right as _) + }) } }