|
|
|
@ -1,12 +1,13 @@
@@ -1,12 +1,13 @@
|
|
|
|
|
//! LCD screens manipulation helper
|
|
|
|
|
|
|
|
|
|
use std::cell::RefCell; |
|
|
|
|
use std::lazy::SyncLazy; |
|
|
|
|
use std::marker::PhantomData; |
|
|
|
|
use std::ops::Drop; |
|
|
|
|
use std::sync::atomic::{AtomicBool, Ordering}; |
|
|
|
|
use std::sync::Mutex; |
|
|
|
|
|
|
|
|
|
use crate::error::{Error, Result}; |
|
|
|
|
use crate::services::gspgpu::{self, FramebufferFormat}; |
|
|
|
|
use crate::services::ServiceHandler; |
|
|
|
|
|
|
|
|
|
/// Trait implemented by TopScreen and BottomScreen for common methods
|
|
|
|
|
pub trait Screen { |
|
|
|
@ -72,9 +73,10 @@ pub enum Side {
@@ -72,9 +73,10 @@ pub enum Side {
|
|
|
|
|
pub struct Gfx { |
|
|
|
|
pub top_screen: RefCell<TopScreen>, |
|
|
|
|
pub bottom_screen: RefCell<BottomScreen>, |
|
|
|
|
_service_handler: ServiceHandler, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static GFX_ACTIVE: AtomicBool = AtomicBool::new(false); |
|
|
|
|
static GFX_ACTIVE: SyncLazy<Mutex<usize>> = SyncLazy::new(|| Mutex::new(0)); |
|
|
|
|
|
|
|
|
|
impl Gfx { |
|
|
|
|
/// Initialize the Gfx module with the chosen framebuffer formats for the top and bottom
|
|
|
|
@ -86,19 +88,22 @@ impl Gfx {
@@ -86,19 +88,22 @@ impl Gfx {
|
|
|
|
|
bottom_fb_fmt: FramebufferFormat, |
|
|
|
|
use_vram_buffers: bool, |
|
|
|
|
) -> Result<Self> { |
|
|
|
|
match GFX_ACTIVE.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst) { |
|
|
|
|
Ok(_) => { |
|
|
|
|
unsafe { |
|
|
|
|
ctru_sys::gfxInit(top_fb_fmt.into(), bottom_fb_fmt.into(), use_vram_buffers); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Ok(Gfx { |
|
|
|
|
top_screen: RefCell::new(TopScreen), |
|
|
|
|
bottom_screen: RefCell::new(BottomScreen), |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
Err(_) => Err(Error::ServiceAlreadyActive("Gfx")), |
|
|
|
|
} |
|
|
|
|
let _service_handler = ServiceHandler::new( |
|
|
|
|
&GFX_ACTIVE, |
|
|
|
|
false, |
|
|
|
|
|| unsafe { |
|
|
|
|
ctru_sys::gfxInit(top_fb_fmt.into(), bottom_fb_fmt.into(), use_vram_buffers); |
|
|
|
|
|
|
|
|
|
Ok(()) |
|
|
|
|
}, |
|
|
|
|
|| unsafe { ctru_sys::gfxExit() }, |
|
|
|
|
)?; |
|
|
|
|
|
|
|
|
|
Ok(Self { |
|
|
|
|
top_screen: RefCell::new(TopScreen), |
|
|
|
|
bottom_screen: RefCell::new(BottomScreen), |
|
|
|
|
_service_handler, |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Creates a new Gfx instance with default init values
|
|
|
|
@ -212,14 +217,6 @@ impl From<Side> for ctru_sys::gfx3dSide_t {
@@ -212,14 +217,6 @@ impl From<Side> for ctru_sys::gfx3dSide_t {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl Drop for Gfx { |
|
|
|
|
fn drop(&mut self) { |
|
|
|
|
unsafe { ctru_sys::gfxExit() }; |
|
|
|
|
|
|
|
|
|
GFX_ACTIVE.store(false, Ordering::SeqCst); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[cfg(test)] |
|
|
|
|
mod tests { |
|
|
|
|
use super::*; |
|
|
|
@ -227,9 +224,6 @@ mod tests {
@@ -227,9 +224,6 @@ mod tests {
|
|
|
|
|
#[test] |
|
|
|
|
fn gfx_duplicate() { |
|
|
|
|
// We don't need to build a `Gfx` because the test runner has one already
|
|
|
|
|
match Gfx::init() { |
|
|
|
|
Err(Error::ServiceAlreadyActive("Gfx")) => return, |
|
|
|
|
_ => panic!(), |
|
|
|
|
} |
|
|
|
|
assert!(matches!(Gfx::init(), Err(Error::ServiceAlreadyActive))) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|