diff --git a/src/gfx.rs b/src/gfx.rs index c767cf5..5a1036c 100644 --- a/src/gfx.rs +++ b/src/gfx.rs @@ -1,31 +1,105 @@ use ::raw::gfx; -pub fn init_default() -> () { - unsafe { - gfx::gfxInitDefault(); +use core::default::Default; +use core::marker::PhantomData; +use core::ops::Drop; + +use ::services::gsp::FramebufferFormat; + +pub struct Gfx { + // we do this to prevent people from making a Gfx struct manually + pd: PhantomData +} + +#[derive(Copy, Clone)] +pub enum Screen { + Top, + Bottom +} + +#[derive(Copy, Clone)] +pub enum Side { + Left, + Right +} + +#[inline] fn screen_to_raw(s: Screen) -> gfx::gfxScreen_t { + match s { + Screen::Top => gfx::gfxScreen_t::GFX_TOP, + Screen::Bottom => gfx::gfxScreen_t::GFX_BOTTOM } } -pub fn exit() -> () { - unsafe { - gfx::gfxExit(); +#[inline] fn side3d_to_raw(s: Side) -> gfx::gfx3dSide_t { + match s { + Side::Left => gfx::gfx3dSide_t::GFX_LEFT, + Side::Right => gfx::gfx3dSide_t::GFX_RIGHT } } -pub fn set_3d_enabled(enabled: bool) -> () { - unsafe { - gfx::gfxSet3D(match enabled { true => 1u8, false => 0u8 }); +impl Gfx { + pub fn set_3d_enabled(&mut self, enabled: bool) { + unsafe { + gfx::gfxSet3D(match enabled { true => 1u8, false => 0u8 }); + } + } + + pub fn get_framebuffer(& mut self, screen: Screen, side: Side) -> (&'static mut [u8], u16, u16) { + unsafe { + use core::slice::from_raw_parts_mut; + + let mut w: u16 = 0; + let mut h: u16 = 0; + let buf: *mut u8 = gfx::gfxGetFramebuffer(screen_to_raw(screen), side3d_to_raw(side), &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) + } + } + + pub fn flush_buffers(&mut self) { + unsafe { gfx::gfxFlushBuffers() }; + } + + pub fn swap_buffers(&mut self) { + unsafe { gfx::gfxSwapBuffers() }; + } + + pub fn swap_buffers_gpu(&mut self) { + unsafe { gfx::gfxSwapBuffersGpu() }; + } + + pub fn get_framebuffer_format(&self, screen: Screen) -> FramebufferFormat { + use core::convert::Into; + unsafe { + gfx::gfxGetScreenFormat(screen_to_raw(screen)).into() + } + } + + pub fn set_framebuffer_format(&mut self, screen: Screen, fmt: FramebufferFormat) { + use core::convert::Into; + unsafe { + gfx::gfxSetScreenFormat(screen_to_raw(screen), fmt.into()) + } + } + + pub fn set_double_buffering(&mut self, screen: Screen, enabled: bool) { + unsafe { + gfx::gfxSetDoubleBuffering(screen_to_raw(screen), match enabled { true => 1u8, false => 0u8 }) + }; } } -pub fn flush_buffers() -> () { - unsafe { - gfx::gfxFlushBuffers(); +impl Default for Gfx { + fn default() -> Self { + unsafe { gfx::gfxInitDefault() }; + Gfx { pd: PhantomData } } } -pub fn swap_buffers() -> () { - unsafe { - gfx::gfxSwapBuffers(); +impl Drop for Gfx { + fn drop(&mut self) { + unsafe { gfx::gfxExit() }; } } diff --git a/src/raw/services/gsp.rs b/src/raw/services/gsp.rs index db9f3da..7a4fd8c 100644 --- a/src/raw/services/gsp.rs +++ b/src/raw/services/gsp.rs @@ -18,6 +18,7 @@ pub struct GSP_FramebufferInfo { } #[repr(C)] +#[derive(Clone, Copy)] pub enum GSP_FramebufferFormats { GSP_RGBA8_OES=0, //pixel_size = 4-bytes GSP_BGR8_OES=1, //pixel_size = 3-bytes diff --git a/src/services/apt.rs b/src/services/apt.rs index bed2ff0..b7e7b82 100644 --- a/src/services/apt.rs +++ b/src/services/apt.rs @@ -1,7 +1,5 @@ use ::Result; -use core::ops::Fn; - use ::raw::services::apt; pub enum AppStatus { @@ -102,7 +100,7 @@ pub fn return_to_menu() -> () { /// false /// }); /// ``` -pub fn main_loop(f: F) -> () where F : Fn() -> bool { +pub fn main_loop(mut f: F) -> () where F : FnMut() -> bool { unsafe { while apt::aptMainLoop() != 0 { if !f() { break; } diff --git a/src/services/gsp.rs b/src/services/gsp.rs index 5ceef53..fb5b6fe 100644 --- a/src/services/gsp.rs +++ b/src/services/gsp.rs @@ -1,5 +1,7 @@ use ::raw::services::gsp; +use core::convert::From; + pub enum Event { Psc0, Psc1, @@ -10,6 +12,56 @@ pub enum Event { DMA } +#[derive(Copy, Clone)] +pub enum FramebufferFormat { + Rgba8, + Bgr8, + Rgb565, + Rgb5A1, + Rgba4 +} + +impl FramebufferFormat { + pub fn pixel_depth_bytes(&self) -> usize { + use self::FramebufferFormat::*; + match *self { + Rgba8 => 4usize, + Bgr8 => 3usize, + Rgb565 => 2usize, + Rgb5A1 => 2usize, + Rgba4 => 2usize + } + } +} + +impl From for FramebufferFormat { + #[inline] fn from(g: gsp::GSP_FramebufferFormats) -> FramebufferFormat { + use ::raw::services::gsp::GSP_FramebufferFormats::*; + use self::FramebufferFormat::*; + match g { + GSP_RGBA8_OES => Rgba8, + GSP_BGR8_OES => Bgr8, + GSP_RGB565_OES => Rgb565, + GSP_RGB5_A1_OES => Rgb5A1, + GSP_RGBA4_OES => Rgba4 + } + } +} + +impl From for gsp::GSP_FramebufferFormats { + #[inline] fn from(g: FramebufferFormat) -> gsp::GSP_FramebufferFormats { + use ::raw::services::gsp::GSP_FramebufferFormats::*; + use self::FramebufferFormat::*; + match g { + Rgba8 => GSP_RGBA8_OES, + Bgr8 => GSP_BGR8_OES, + Rgb565 => GSP_RGB565_OES, + Rgb5A1 => GSP_RGB5_A1_OES, + Rgba4 => GSP_RGBA4_OES + } + } +} + fn to_raw_event(ev: Event) -> gsp::GSP_Event { use ::raw::services::gsp::GSP_Event::*; use self::Event::*;