|
|
@ -1,5 +1,6 @@ |
|
|
|
//! LCD screens manipulation helper
|
|
|
|
//! LCD screens manipulation helper
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use std::cell::{BorrowError, BorrowMutError, Ref, RefCell, RefMut}; |
|
|
|
use std::default::Default; |
|
|
|
use std::default::Default; |
|
|
|
use std::ops::Drop; |
|
|
|
use std::ops::Drop; |
|
|
|
|
|
|
|
|
|
|
@ -9,7 +10,10 @@ use crate::services::gspgpu::{self, FramebufferFormat}; |
|
|
|
/// provides helper functions and utilities for software rendering.
|
|
|
|
/// provides helper functions and utilities for software rendering.
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// The service exits when this struct is dropped.
|
|
|
|
/// The service exits when this struct is dropped.
|
|
|
|
pub struct Gfx(()); |
|
|
|
pub struct Gfx { |
|
|
|
|
|
|
|
top_screen: RefCell<Screen>, |
|
|
|
|
|
|
|
bottom_screen: RefCell<Screen>, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Available screens on the 3DS
|
|
|
|
/// Available screens on the 3DS
|
|
|
|
#[derive(Copy, Clone, Debug)] |
|
|
|
#[derive(Copy, Clone, Debug)] |
|
|
@ -44,32 +48,30 @@ impl Gfx { |
|
|
|
unsafe { |
|
|
|
unsafe { |
|
|
|
ctru_sys::gfxInit(top_fb_fmt.into(), bottom_fb_fmt.into(), use_vram_buffers); |
|
|
|
ctru_sys::gfxInit(top_fb_fmt.into(), bottom_fb_fmt.into(), use_vram_buffers); |
|
|
|
} |
|
|
|
} |
|
|
|
Gfx(()) |
|
|
|
Gfx { |
|
|
|
|
|
|
|
top_screen: RefCell::new(Screen::Top), |
|
|
|
|
|
|
|
bottom_screen: RefCell::new(Screen::Bottom), |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Enable or disable the 3D stereoscopic effect
|
|
|
|
/// Try to get an immutable reference to the Top screen
|
|
|
|
pub fn set_3d_enabled(&mut self, enabled: bool) { |
|
|
|
pub fn get_top_screen(&self) -> Result<Ref<'_, Screen>, BorrowError> { |
|
|
|
unsafe { ctru_sys::gfxSet3D(enabled) } |
|
|
|
self.top_screen.try_borrow() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Enable or disable the wide screen mode (top screen).
|
|
|
|
/// Try to get a mutable reference to the Top screen
|
|
|
|
///
|
|
|
|
pub fn get_top_screen_mut(&self) -> Result<RefMut<'_, Screen>, BorrowMutError> { |
|
|
|
/// This only works when 3D is disabled.
|
|
|
|
self.top_screen.try_borrow_mut() |
|
|
|
pub fn set_wide_mode(&mut self, enabled: bool) { |
|
|
|
|
|
|
|
unsafe { ctru_sys::gfxSetWide(enabled) }; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Get the status of wide screen mode.
|
|
|
|
/// Try to get an immutable reference to the Bottom screen
|
|
|
|
pub fn get_wide_mode(&self) -> bool { |
|
|
|
pub fn get_bottom_screen(&self) -> Result<Ref<'_, Screen>, BorrowError> { |
|
|
|
unsafe { ctru_sys::gfxIsWide() } |
|
|
|
self.bottom_screen.try_borrow() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Sets whether to use double buffering. Enabled by default.
|
|
|
|
/// Try to get a mutable reference to the Bottom screen
|
|
|
|
///
|
|
|
|
pub fn get_bottom_screen_mut(&self) -> Result<RefMut<'_, Screen>, BorrowMutError> { |
|
|
|
/// Note that even when double buffering is disabled, one should still use the `swap_buffers`
|
|
|
|
self.bottom_screen.try_borrow_mut() |
|
|
|
/// method on each frame to keep the gsp configuration up to date
|
|
|
|
|
|
|
|
pub fn set_double_buffering(&mut self, screen: Screen, enabled: bool) { |
|
|
|
|
|
|
|
unsafe { ctru_sys::gfxSetDoubleBuffering(screen.into(), enabled) } |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Flushes the current framebuffers
|
|
|
|
/// Flushes the current framebuffers
|
|
|
@ -97,13 +99,63 @@ impl Gfx { |
|
|
|
pub fn wait_for_vblank(&self) { |
|
|
|
pub fn wait_for_vblank(&self) { |
|
|
|
gspgpu::wait_for_event(gspgpu::Event::VBlank0, true); |
|
|
|
gspgpu::wait_for_event(gspgpu::Event::VBlank0, true); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl Screen { |
|
|
|
|
|
|
|
/// Enable or disable the 3D stereoscopic effect
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// #Errors
|
|
|
|
|
|
|
|
/// When called by the Bottom screen
|
|
|
|
|
|
|
|
pub fn set_3d_enabled(&mut self, enabled: bool) -> Result<(), String> { |
|
|
|
|
|
|
|
match self { |
|
|
|
|
|
|
|
Screen::Top => unsafe { |
|
|
|
|
|
|
|
ctru_sys::gfxSet3D(enabled); |
|
|
|
|
|
|
|
Ok(()) |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
Screen::Bottom => Err("Tried to enable 3D on bottom screen".to_string()), |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Gets the framebuffer format for a screen
|
|
|
|
/// Enable or disable the wide screen mode (top screen).
|
|
|
|
|
|
|
|
/// This only works when 3D is disabled.
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// #Errors
|
|
|
|
|
|
|
|
/// When called by the Bottom screen
|
|
|
|
|
|
|
|
pub fn set_wide_mode(&mut self, enabled: bool) -> Result<(), String> { |
|
|
|
|
|
|
|
match self { |
|
|
|
|
|
|
|
Screen::Top => unsafe { |
|
|
|
|
|
|
|
ctru_sys::gfxSetWide(enabled); |
|
|
|
|
|
|
|
Ok(()) |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
Screen::Bottom => Err("Tried to change wide-mode on bottom screen".to_string()), |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Get the status of wide screen mode.
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// #Errors
|
|
|
|
|
|
|
|
/// When called by the Bottom screen
|
|
|
|
|
|
|
|
pub fn get_wide_mode(&self) -> Result<bool, String> { |
|
|
|
|
|
|
|
match self { |
|
|
|
|
|
|
|
Screen::Top => unsafe { Ok(ctru_sys::gfxIsWide()) }, |
|
|
|
|
|
|
|
Screen::Bottom => Err("Tried to check wide-mode status on bottom screen".to_string()), |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// 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(&mut self, screen: Screen, enabled: bool) { |
|
|
|
|
|
|
|
unsafe { ctru_sys::gfxSetDoubleBuffering(screen.into(), enabled) } |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Gets the framebuffer format
|
|
|
|
pub fn get_framebuffer_format(&self, screen: Screen) -> FramebufferFormat { |
|
|
|
pub fn get_framebuffer_format(&self, screen: Screen) -> FramebufferFormat { |
|
|
|
unsafe { ctru_sys::gfxGetScreenFormat(screen.into()).into() } |
|
|
|
unsafe { ctru_sys::gfxGetScreenFormat(screen.into()).into() } |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Change the framebuffer format for a screen
|
|
|
|
/// Change the framebuffer format
|
|
|
|
pub fn set_framebuffer_format(&mut self, screen: Screen, fmt: FramebufferFormat) { |
|
|
|
pub fn set_framebuffer_format(&mut self, screen: Screen, fmt: FramebufferFormat) { |
|
|
|
unsafe { ctru_sys::gfxSetScreenFormat(screen.into(), fmt.into()) } |
|
|
|
unsafe { ctru_sys::gfxSetScreenFormat(screen.into(), fmt.into()) } |
|
|
|
} |
|
|
|
} |
|
|
@ -114,13 +166,15 @@ impl Gfx { |
|
|
|
///
|
|
|
|
///
|
|
|
|
/// Note that the pointer returned by this function can change after each call to this function
|
|
|
|
/// Note that the pointer returned by this function can change after each call to this function
|
|
|
|
/// if double buffering is enabled
|
|
|
|
/// if double buffering is enabled
|
|
|
|
pub unsafe fn get_raw_framebuffer(&self, screen: Screen, side: Side) -> (*mut u8, u16, u16) { |
|
|
|
pub fn get_raw_framebuffer(&self, screen: Screen, side: Side) -> (*mut u8, u16, u16) { |
|
|
|
let mut width: u16 = 0; |
|
|
|
let mut width: u16 = 0; |
|
|
|
let mut height: u16 = 0; |
|
|
|
let mut height: u16 = 0; |
|
|
|
|
|
|
|
unsafe { |
|
|
|
let buf: *mut u8 = |
|
|
|
let buf: *mut u8 = |
|
|
|
ctru_sys::gfxGetFramebuffer(screen.into(), side.into(), &mut width, &mut height); |
|
|
|
ctru_sys::gfxGetFramebuffer(screen.into(), side.into(), &mut width, &mut height); |
|
|
|
(buf, width, height) |
|
|
|
(buf, width, height) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl From<Screen> for ctru_sys::gfxScreen_t { |
|
|
|
impl From<Screen> for ctru_sys::gfxScreen_t { |
|
|
@ -146,7 +200,10 @@ impl From<Side> for ctru_sys::gfx3dSide_t { |
|
|
|
impl Default for Gfx { |
|
|
|
impl Default for Gfx { |
|
|
|
fn default() -> Self { |
|
|
|
fn default() -> Self { |
|
|
|
unsafe { ctru_sys::gfxInitDefault() }; |
|
|
|
unsafe { ctru_sys::gfxInitDefault() }; |
|
|
|
Gfx(()) |
|
|
|
Gfx { |
|
|
|
|
|
|
|
top_screen: RefCell::new(Screen::Top), |
|
|
|
|
|
|
|
bottom_screen: RefCell::new(Screen::Bottom), |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|