aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFenrirWolf <[email protected]>2018-08-26 18:41:42 -0600
committerGitHub <[email protected]>2018-08-26 18:41:42 -0600
commit97c7652fdd5168248b34c07a3e9eac66435cd94a (patch)
tree9c0a2e746958a1a4eeb571f32aa0bcc0d75d3d26
parentWrite entire panic message to stderr at once (diff)
parentUpdate and document Gfx module (diff)
downloadctru-rs-97c7652fdd5168248b34c07a3e9eac66435cd94a.tar.xz
ctru-rs-97c7652fdd5168248b34c07a3e9eac66435cd94a.zip
Merge pull request #74 from FenrirWolf/gfx
Update and document Gfx module
-rw-r--r--ctru-rs/Cargo.toml2
-rw-r--r--ctru-rs/src/gfx.rs148
-rw-r--r--ctru-rs/src/services/gspgpu.rs78
3 files changed, 124 insertions, 104 deletions
diff --git a/ctru-rs/Cargo.toml b/ctru-rs/Cargo.toml
index 1484b64..3ac66d1 100644
--- a/ctru-rs/Cargo.toml
+++ b/ctru-rs/Cargo.toml
@@ -3,7 +3,7 @@ authors = ["Ronald Kinard <[email protected]>"]
description = "A safe wrapper around smealum's ctrulib."
license = "https://en.wikipedia.org/wiki/Zlib_License"
name = "ctru-rs"
-version = "0.7.0"
+version = "0.7.1"
[lib]
crate-type = ["rlib"]
diff --git a/ctru-rs/src/gfx.rs b/ctru-rs/src/gfx.rs
index 4f55271..749a69a 100644
--- a/ctru-rs/src/gfx.rs
+++ b/ctru-rs/src/gfx.rs
@@ -1,118 +1,138 @@
+//! LCD screens manipulation helper
+
use std::default::Default;
use std::ops::Drop;
-use services::gspgpu::FramebufferFormat;
+use services::gspgpu::{self, FramebufferFormat};
+/// A handle to libctru's gfx module. This module is a wrapper around the GSPGPU service that
+/// provides helper functions and utilities for software rendering.
+///
+/// The service exits when this struct is dropped.
pub struct Gfx(());
-#[derive(Copy, Clone)]
+/// Available screens on the 3DS
+#[derive(Copy, Clone, Debug)]
pub enum Screen {
+ /// The top screen
Top,
+ /// The bottom screen
Bottom,
}
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
+/// Side of top screen framebuffer
+///
+/// The top screen of the 3DS can have two separate sets of framebuffers to support its 3D functionality
pub enum Side {
+ /// The left framebuffer. This framebuffer is also the one used when 3D is disabled
Left,
+ /// The right framebuffer
Right,
}
-impl From<::libctru::gfxScreen_t> for Screen {
- fn from(g: ::libctru::gfxScreen_t) -> Screen {
- use self::Screen::*;
- match g {
- ::libctru::GFX_TOP => Top,
- ::libctru::GFX_BOTTOM => Bottom,
- _ => unreachable!(),
- }
- }
-}
-
-impl From<Screen> for ::libctru::gfxScreen_t {
- fn from(g: Screen) -> ::libctru::gfxScreen_t {
- use self::Screen::*;
- match g {
- Top => ::libctru::GFX_TOP,
- Bottom => ::libctru::GFX_BOTTOM,
- }
- }
-}
-
-impl From<::libctru::gfx3dSide_t> for Side {
- fn from(s: ::libctru::gfx3dSide_t) -> Side {
- use self::Side::*;
- match s {
- ::libctru::GFX_LEFT => Left,
- ::libctru::GFX_RIGHT => Right,
- _ => unreachable!(),
- }
- }
-}
-
-impl From<Side> for ::libctru::gfx3dSide_t {
- fn from(s: Side) -> ::libctru::gfx3dSide_t {
- use self::Side::*;
- match s {
- Left => ::libctru::GFX_LEFT,
- Right => ::libctru::GFX_RIGHT,
- }
+impl Gfx {
+ /// Initialize the Gfx module with the chosen framebuffer formats for the top and bottom
+ /// screens
+ ///
+ /// Use `Gfx::default()` instead of this function to initialize the module with default parameters
+ pub fn new(
+ top_fb_fmt: FramebufferFormat, bottom_fb_fmt: FramebufferFormat, use_vram_buffers: bool) -> Self {
+ unsafe { ::libctru::gfxInit(top_fb_fmt.into(), bottom_fb_fmt.into(), use_vram_buffers); }
+ Gfx(())
}
-}
-impl Gfx {
+ /// Enable or disable the 3D stereoscopic effect
pub fn set_3d_enabled(&self, enabled: bool) {
unsafe {
::libctru::gfxSet3D(enabled)
}
}
- pub fn get_framebuffer(&self, screen: Screen, side: Side) -> (&'static mut [u8], u16, u16) {
+ /// 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(&self, screen: Screen, enabled: bool) {
unsafe {
- use std::slice::from_raw_parts_mut;
-
- let mut w: u16 = 0;
- let mut h: u16 = 0;
- let buf: *mut u8 = ::libctru::gfxGetFramebuffer(screen.into(),
- side.into(),
- &mut w as *mut u16,
- &mut h as &mut u16);
-
- let fbfmt = self.get_framebuffer_format(screen);
-
- (from_raw_parts_mut(buf, (w as usize * h as usize) * fbfmt.pixel_depth_bytes()), w, h)
+ ::libctru::gfxSetDoubleBuffering(screen.into(), enabled)
}
}
+ /// Flushes the current framebuffers
pub fn flush_buffers(&self) {
unsafe { ::libctru::gfxFlushBuffers() };
}
+ /// Swaps the framebuffers and sets the gsp state
+ ///
+ /// Use this function when working with software rendering
pub fn swap_buffers(&self) {
unsafe { ::libctru::gfxSwapBuffers() };
}
+ /// Swaps the framebuffers without manipulating the gsp state
+ ///
+ /// Use this function when working with GPU rendering
pub fn swap_buffers_gpu(&self) {
unsafe { ::libctru::gfxSwapBuffersGpu() };
}
+ /// Waits for the vertical blank interrupt
+ ///
+ /// Use this to synchronize your application with the refresh rate of the LCD screens
+ pub fn wait_for_vblank(&self) {
+ gspgpu::wait_for_event(gspgpu::Event::VBlank0, true);
+
+ }
+
+ /// Gets the framebuffer format for a screen
pub fn get_framebuffer_format(&self, screen: Screen) -> FramebufferFormat {
unsafe { ::libctru::gfxGetScreenFormat(screen.into()).into() }
}
- pub fn set_framebuffer_format(&self, screen: Screen,
- fmt: FramebufferFormat) {
+ /// Change the framebuffer format for a screen
+ pub fn set_framebuffer_format(&self, screen: Screen, fmt: FramebufferFormat) {
unsafe { ::libctru::gfxSetScreenFormat(screen.into(), fmt.into()) }
}
- pub fn set_double_buffering(&self, screen: Screen, enabled: bool) {
+ /// 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) {
unsafe {
- ::libctru::gfxSetDoubleBuffering(screen.into(), enabled)
+ let mut width: u16 = 0;
+ let mut height: u16 = 0;
+ let buf: *mut u8 = ::libctru::gfxGetFramebuffer(
+ screen.into(),
+ side.into(),
+ &mut width,
+ &mut height,
+ );
+ (buf, width, height)
}
}
+}
- pub fn wait_for_vblank(&self) {
- unsafe {
- ::libctru::gspWaitForEvent(::libctru::GSPGPU_EVENT_VBlank0, true)
+impl From<Screen> for ::libctru::gfxScreen_t {
+ fn from(g: Screen) -> ::libctru::gfxScreen_t {
+ use self::Screen::*;
+ match g {
+ Top => ::libctru::GFX_TOP,
+ Bottom => ::libctru::GFX_BOTTOM,
+ }
+ }
+}
+
+impl From<Side> for ::libctru::gfx3dSide_t {
+ fn from(s: Side) -> ::libctru::gfx3dSide_t {
+ use self::Side::*;
+ match s {
+ Left => ::libctru::GFX_LEFT,
+ Right => ::libctru::GFX_RIGHT,
}
}
}
diff --git a/ctru-rs/src/services/gspgpu.rs b/ctru-rs/src/services/gspgpu.rs
index b36cb36..b047493 100644
--- a/ctru-rs/src/services/gspgpu.rs
+++ b/ctru-rs/src/services/gspgpu.rs
@@ -1,5 +1,8 @@
+//! GSPGPU service
+
use std::convert::From;
+#[derive(Copy, Clone, Debug)]
pub enum Event {
Psc0,
Psc1,
@@ -10,31 +13,46 @@ pub enum Event {
DMA,
}
-#[derive(Copy, Clone)]
+/// The different framebuffer formats supported by the 3DS
+#[derive(Copy, Clone, Debug)]
pub enum FramebufferFormat {
+ /// RGBA8. 4 bytes per pixel
Rgba8,
+ /// BGR8. 3 bytes per pixel
Bgr8,
+ /// RGB565. 2 bytes per pixel
Rgb565,
+ /// RGB5A1. 2 bytes per pixel
Rgb5A1,
+ /// RGBA4. 2 bytes per pixel
Rgba4,
}
impl FramebufferFormat {
+ /// Returns the number of bytes per pixel used by this FramebufferFormat
pub fn pixel_depth_bytes(&self) -> usize {
use self::FramebufferFormat::*;
match *self {
- Rgba8 => 4usize,
- Bgr8 => 3usize,
- Rgb565 => 2usize,
- Rgb5A1 => 2usize,
- Rgba4 => 2usize,
+ Rgba8 => 4,
+ Bgr8 => 3,
+ Rgb565 => 2,
+ Rgb5A1 => 2,
+ Rgba4 => 2,
}
}
}
+/// Waits for a GSPGPU event to occur.
+///
+/// `discard_current` determines whether to discard the current event and wait for the next event
+pub fn wait_for_event(ev: Event, discard_current: bool) {
+ unsafe {
+ ::libctru::gspWaitForEvent(ev.into(), discard_current);
+ }
+}
+
impl From<::libctru::GSPGPU_FramebufferFormats> for FramebufferFormat {
- #[inline]
- fn from(g: ::libctru::GSPGPU_FramebufferFormats) -> FramebufferFormat {
+ fn from(g: ::libctru::GSPGPU_FramebufferFormats) -> Self {
use self::FramebufferFormat::*;
match g {
::libctru::GSP_RGBA8_OES => Rgba8,
@@ -48,8 +66,7 @@ impl From<::libctru::GSPGPU_FramebufferFormats> for FramebufferFormat {
}
impl From<FramebufferFormat> for ::libctru::GSPGPU_FramebufferFormats {
- #[inline]
- fn from(g: FramebufferFormat) -> ::libctru::GSPGPU_FramebufferFormats {
+ fn from(g: FramebufferFormat) -> Self {
use self::FramebufferFormat::*;
match g {
Rgba8 => ::libctru::GSP_RGBA8_OES,
@@ -61,34 +78,17 @@ impl From<FramebufferFormat> for ::libctru::GSPGPU_FramebufferFormats {
}
}
-fn to_raw_event(ev: Event) -> ::libctru::GSPGPU_Event {
- use self::Event::*;
-
- match ev {
- Psc0 => ::libctru::GSPGPU_EVENT_PSC0,
- Psc1 => ::libctru::GSPGPU_EVENT_PSC1,
- VBlank0 => ::libctru::GSPGPU_EVENT_VBlank0,
- VBlank1 => ::libctru::GSPGPU_EVENT_VBlank1,
- PPF => ::libctru::GSPGPU_EVENT_PPF,
- P3D => ::libctru::GSPGPU_EVENT_P3D,
- DMA => ::libctru::GSPGPU_EVENT_DMA,
- }
-}
-
-/// Sleep until GSP event fires.
-///
-/// # Examples
-///
-/// Wait for VBlank.
-///
-/// ```
-/// use ctru::services::apt;
-/// apt::main_loop(|| {
-/// wait_for_event(Event::VBlank0);
-/// });
-pub fn wait_for_event(ev: Event) -> () {
- unsafe {
- // TODO second argument?
- ::libctru::gspWaitForEvent(to_raw_event(ev), false);
+impl From<Event> for ::libctru::GSPGPU_Event {
+ fn from(ev: Event) -> Self {
+ use self::Event::*;
+ match ev {
+ Psc0 => ::libctru::GSPGPU_EVENT_PSC0,
+ Psc1 => ::libctru::GSPGPU_EVENT_PSC1,
+ VBlank0 => ::libctru::GSPGPU_EVENT_VBlank0,
+ VBlank1 => ::libctru::GSPGPU_EVENT_VBlank1,
+ PPF => ::libctru::GSPGPU_EVENT_PPF,
+ P3D => ::libctru::GSPGPU_EVENT_P3D,
+ DMA => ::libctru::GSPGPU_EVENT_DMA,
+ }
}
}