1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
//! GSPGPU service

/// GSPGPU events that can be awaited.
#[doc(alias = "GSPGPU_Event")]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u8)]
pub enum Event {
    /// Memory fill 1 completed.
    Psc0 = ctru_sys::GSPGPU_EVENT_PSC0,
    /// Memory fill 2 completed.
    Psc1 = ctru_sys::GSPGPU_EVENT_PSC1,
    /// Top screen VBlank.
    VBlank0 = ctru_sys::GSPGPU_EVENT_VBlank0,
    /// Bottom screen VBlank.
    VBlank1 = ctru_sys::GSPGPU_EVENT_VBlank1,
    /// Display transfer completed.
    PPF = ctru_sys::GSPGPU_EVENT_PPF,
    /// Command list processing completed.
    P3D = ctru_sys::GSPGPU_EVENT_P3D,
    /// Direct Memory Access requested.
    DMA = ctru_sys::GSPGPU_EVENT_DMA,
}

#[doc(alias = "GSPGPU_FramebufferFormat")]
/// Framebuffer formats supported by the 3DS' screens.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u8)]
pub enum FramebufferFormat {
    /// RGBA8. 4 bytes per pixel
    Rgba8 = ctru_sys::GSP_RGBA8_OES,
    /// BGR8. 3 bytes per pixel
    Bgr8 = ctru_sys::GSP_BGR8_OES,
    /// RGB565. 2 bytes per pixel
    Rgb565 = ctru_sys::GSP_RGB565_OES,
    /// RGB5A1. 2 bytes per pixel
    Rgb5A1 = ctru_sys::GSP_RGB5_A1_OES,
    /// RGBA4. 2 bytes per pixel
    Rgba4 = ctru_sys::GSP_RGBA4_OES,
}

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 => 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
#[doc(alias = "gspWaitForEvent")]
pub fn wait_for_event(ev: Event, discard_current: bool) {
    unsafe {
        ctru_sys::gspWaitForEvent(ev.into(), discard_current);
    }
}

impl From<ctru_sys::GSPGPU_FramebufferFormat> for FramebufferFormat {
    fn from(g: ctru_sys::GSPGPU_FramebufferFormat) -> Self {
        use self::FramebufferFormat::*;
        match g {
            ctru_sys::GSP_RGBA8_OES => Rgba8,
            ctru_sys::GSP_BGR8_OES => Bgr8,
            ctru_sys::GSP_RGB565_OES => Rgb565,
            ctru_sys::GSP_RGB5_A1_OES => Rgb5A1,
            ctru_sys::GSP_RGBA4_OES => Rgba4,
            _ => unreachable!(),
        }
    }
}

from_impl!(FramebufferFormat, ctru_sys::GSPGPU_FramebufferFormat);
from_impl!(Event, ctru_sys::GSPGPU_Event);