Browse Source

Initial pass of Swap/Flush traits for screens

pull/118/head
Ian Chamberlain 2 years ago
parent
commit
683fad4aee
No known key found for this signature in database
GPG Key ID: AE5484D09405AA60
  1. 4
      ctru-rs/Cargo.toml
  2. 2
      ctru-rs/examples/camera-image.rs
  3. 14
      ctru-rs/examples/gfx-3d-mode.rs
  4. 2
      ctru-rs/examples/graphics-bitmap.rs
  5. 2
      ctru-rs/src/lib.rs
  6. 97
      ctru-rs/src/services/gfx.rs

4
ctru-rs/Cargo.toml

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
[package]
authors = [ "Rust3DS Org", "Ronald Kinard <furyhunter600@gmail.com>" ]
authors = ["Rust3DS Org", "Ronald Kinard <furyhunter600@gmail.com>"]
description = "A safe wrapper around smealum's ctrulib."
license = "Zlib"
name = "ctru-rs"
@ -15,7 +15,7 @@ name = "ctru" @@ -15,7 +15,7 @@ name = "ctru"
cfg-if = "1.0"
ctru-sys = { path = "../ctru-sys", version = "21.2" }
const-zero = "0.1.0"
linker-fix-3ds = { git = "https://github.com/rust3ds/rust-linker-fix-3ds.git" }
shim-3ds = { git = "https://github.com/rust3ds/shim-3ds.git" }
pthread-3ds = { git = "https://github.com/rust3ds/pthread-3ds.git" }
libc = "0.2.121"
bitflags = "1.0.0"

2
ctru-rs/examples/camera-image.rs

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
use ctru::prelude::*;
use ctru::services::cam::{Cam, Camera, OutputFormat, ShutterSound, ViewSize};
use ctru::services::gfx::Screen;
use ctru::services::gfx::{Flush, Screen, Swap};
use ctru::services::gspgpu::FramebufferFormat;
use std::time::Duration;

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

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
use ctru::prelude::*;
use ctru::services::gfx::{Screen, Side, TopScreen3D};
use ctru::services::gfx::{Screen, Side, Swap, TopScreen3D};
/// See `graphics-bitmap.rs` for details on how the image is generated.
///
@ -21,8 +21,7 @@ fn main() { @@ -21,8 +21,7 @@ fn main() {
gfx.top_screen.borrow_mut().set_double_buffering(true);
let top_screen = TopScreen3D::from(&gfx.top_screen);
let (mut left, mut right) = top_screen.split_mut();
let mut top_screen = TopScreen3D::from(&gfx.top_screen);
let mut current_side = Side::Left;
@ -35,6 +34,8 @@ fn main() { @@ -35,6 +34,8 @@ fn main() {
break;
}
let (mut left, mut right) = top_screen.split_mut();
let left_buf = left.raw_framebuffer();
let right_buf = right.raw_framebuffer();
@ -61,8 +62,11 @@ fn main() { @@ -61,8 +62,11 @@ fn main() {
buf.copy_from(IMAGE.as_ptr(), IMAGE.len());
}
left.flush_buffer();
left.swap_buffers();
drop(left);
drop(right);
top_screen.flush_buffers();
top_screen.swap_buffers();
//Wait for VBlank
gfx.wait_for_vblank();

2
ctru-rs/examples/graphics-bitmap.rs

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
use ctru::prelude::*;
use ctru::services::gfx::Screen;
use ctru::services::gfx::{Flush, Screen, Swap};
/// Ferris image taken from <https://rustacean.net> and scaled down to 320x240px.
/// To regenerate the data, you will need to install `imagemagick` and run this

2
ctru-rs/src/lib.rs

@ -8,8 +8,8 @@ @@ -8,8 +8,8 @@
#![test_runner(test_runner::run)]
// Nothing is imported from these crates but their inclusion here assures correct linking of the missing implementations.
extern crate linker_fix_3ds;
extern crate pthread_3ds;
extern crate shim_3ds;
#[no_mangle]
#[cfg(feature = "big-stack")]

97
ctru-rs/src/services/gfx.rs

@ -9,11 +9,12 @@ use crate::services::gspgpu::{self, FramebufferFormat}; @@ -9,11 +9,12 @@ use crate::services::gspgpu::{self, FramebufferFormat};
use crate::services::ServiceReference;
mod private {
use super::{BottomScreen, TopScreen, TopScreenLeft, TopScreenRight};
use super::{BottomScreen, TopScreen, TopScreen3D, TopScreenLeft, TopScreenRight};
pub trait Sealed {}
impl Sealed for TopScreen {}
impl Sealed for TopScreen3D<'_> {}
impl Sealed for TopScreenLeft {}
impl Sealed for TopScreenRight {}
impl Sealed for BottomScreen {}
@ -55,28 +56,6 @@ pub trait Screen: private::Sealed { @@ -55,28 +56,6 @@ pub trait Screen: private::Sealed {
unsafe { ctru_sys::gfxSetDoubleBuffering(self.as_raw(), enabled) }
}
/// Swaps the video buffers.
///
/// This should be used even if double buffering is disabled.
fn flush_buffer(&mut self) {
let framebuffer = self.raw_framebuffer();
// Flush the data array. `self.raw_framebuffer` should get the correct parameters for all kinds of screens
unsafe {
ctru_sys::GSPGPU_FlushDataCache(
framebuffer.ptr.cast(),
(framebuffer.height * framebuffer.width) as u32,
)
};
}
/// Swaps the video buffers.
///
/// This should be used even if double buffering is disabled.
fn swap_buffers(&mut self) {
unsafe { ctru_sys::gfxScreenSwapBuffers(self.side().into(), true) };
}
/// Gets the framebuffer format
fn framebuffer_format(&self) -> FramebufferFormat {
unsafe { ctru_sys::gfxGetScreenFormat(self.as_raw()) }.into()
@ -101,13 +80,77 @@ pub struct TopScreen3D<'top_screen> { @@ -101,13 +80,77 @@ pub struct TopScreen3D<'top_screen> {
screen: &'top_screen RefCell<TopScreen>,
}
struct TopScreenLeft;
pub trait Swap: private::Sealed {
fn swap_buffers(&mut self);
}
trait SwappableScreen: Screen {}
impl SwappableScreen for TopScreen {}
impl SwappableScreen for BottomScreen {}
impl<S: SwappableScreen> Swap for S {
fn swap_buffers(&mut self) {
unsafe {
ctru_sys::gfxScreenSwapBuffers(self.side().into(), false);
}
}
}
pub trait Flush: private::Sealed {
fn flush_buffer(&mut self);
}
struct TopScreenRight;
trait FlushableScreen: Screen {}
impl FlushableScreen for TopScreen {}
impl FlushableScreen for BottomScreen {}
impl FlushableScreen for TopScreenLeft {}
impl FlushableScreen for TopScreenRight {}
impl<S: FlushableScreen> Flush for S {
fn flush_buffer(&mut self) {
let framebuffer = self.raw_framebuffer();
// Flush the data array. `self.raw_framebuffer` should get the correct parameters for all kinds of screens
unsafe {
ctru_sys::GSPGPU_FlushDataCache(
framebuffer.ptr.cast(),
(framebuffer.height * framebuffer.width) as u32,
)
};
}
}
impl Swap for TopScreen3D<'_> {
fn swap_buffers(&mut self) {
unsafe {
ctru_sys::gfxScreenSwapBuffers(Side::Left.into(), true);
}
}
}
impl TopScreen3D<'_> {
/// Flush the buffers for both the left and right sides of the screen.
pub fn flush_buffers(&mut self) {
let (mut left, mut right) = self.split_mut();
left.flush_buffer();
right.flush_buffer();
}
}
/// The left side of the top screen, when using 3D mode.
#[derive(Debug)]
#[non_exhaustive]
pub struct TopScreenLeft;
/// The right side of the top screen, when using 3D mode.
#[derive(Debug)]
#[non_exhaustive]
pub struct TopScreenRight;
/// The bottom screen. Mutable access to this struct is required to write to the
/// bottom screen's frame buffer.
#[derive(Debug)]
#[non_exhaustive]
pub struct BottomScreen;
/// Representation of a framebuffer for one [`Side`] of the top screen, or the
@ -194,14 +237,14 @@ impl Gfx { @@ -194,14 +237,14 @@ impl Gfx {
impl TopScreen3D<'_> {
/// Immutably borrow the two sides of the screen as `(left, right)`.
pub fn split(&self) -> (Ref<dyn Screen>, Ref<dyn Screen>) {
pub fn split(&self) -> (Ref<TopScreenLeft>, Ref<TopScreenRight>) {
Ref::map_split(self.screen.borrow(), |screen| {
(&screen.left as _, &screen.right as _)
})
}
/// Mutably borrow the two sides of the screen as `(left, right)`.
pub fn split_mut(&self) -> (RefMut<dyn Screen>, RefMut<dyn Screen>) {
pub fn split_mut(&self) -> (RefMut<TopScreenLeft>, RefMut<TopScreenRight>) {
RefMut::map_split(self.screen.borrow_mut(), |screen| {
(&mut screen.left as _, &mut screen.right as _)
})

Loading…
Cancel
Save