citro3d/
texenv.rs

1//! Texture combiner support. See <https://www.khronos.org/opengl/wiki/Texture_Combiners>
2//! for more details.
3
4use bitflags::bitflags;
5
6/// A texture combiner, also called a "texture environment" (hence the struct name).
7/// See also [`texenv.h` documentation](https://oreo639.github.io/citro3d/texenv_8h.html).
8#[doc(alias = "C3D_TexEnv")]
9pub struct TexEnv(*mut citro3d_sys::C3D_TexEnv);
10
11// https://oreo639.github.io/citro3d/texenv_8h.html#a9eda91f8e7252c91f873b1d43e3728b6
12pub(crate) const TEXENV_COUNT: usize = 6;
13
14impl TexEnv {
15    pub(crate) fn new(stage: Stage) -> Self {
16        let mut result = unsafe { Self(citro3d_sys::C3D_GetTexEnv(stage.0 as _)) };
17        result.reset();
18        result
19    }
20
21    /// Re-initialize the texture combiner to its default state.
22    pub fn reset(&mut self) {
23        unsafe {
24            citro3d_sys::C3D_TexEnvInit(self.0);
25        }
26    }
27
28    /// Configure the source values of the texture combiner.
29    ///
30    /// # Parameters
31    ///
32    /// - `mode`: which [`Mode`]\(s) to set the sourc operand(s) for.
33    /// - `source0`: the first [`Source`] operand to the texture combiner
34    /// - `source1` and `source2`: optional additional [`Source`] operands to use
35    #[doc(alias = "C3D_TexEnvSrc")]
36    pub fn src(
37        &mut self,
38        mode: Mode,
39        source0: Source,
40        source1: Option<Source>,
41        source2: Option<Source>,
42    ) -> &mut Self {
43        unsafe {
44            citro3d_sys::C3D_TexEnvSrc(
45                self.0,
46                mode.bits(),
47                source0 as _,
48                source1.unwrap_or(Source::PrimaryColor) as _,
49                source2.unwrap_or(Source::PrimaryColor) as _,
50            );
51        }
52        self
53    }
54
55    /// Configure the texture combination function.
56    ///
57    /// # Parameters
58    ///
59    /// - `mode`: the [`Mode`]\(s) the combination function will apply to.
60    /// - `func`: the [`CombineFunc`] used to combine textures.
61    #[doc(alias = "C3D_TexEnvFunc")]
62    pub fn func(&mut self, mode: Mode, func: CombineFunc) -> &mut Self {
63        unsafe {
64            citro3d_sys::C3D_TexEnvFunc(self.0, mode.bits(), func as _);
65        }
66
67        self
68    }
69}
70
71bitflags! {
72    /// Whether to operate on colors, alpha values, or both.
73    #[doc(alias = "C3D_TexEnvMode")]
74    pub struct Mode: citro3d_sys::C3D_TexEnvMode {
75        #[allow(missing_docs)]
76        const RGB = citro3d_sys::C3D_RGB;
77        #[allow(missing_docs)]
78        const ALPHA = citro3d_sys::C3D_Alpha;
79        #[allow(missing_docs)]
80        const BOTH = citro3d_sys::C3D_Both;
81    }
82}
83
84/// A source operand of a [`TexEnv`]'s texture combination.
85#[doc(alias = "GPU_TEVSRC")]
86#[allow(missing_docs)]
87#[derive(Debug, Clone, Copy)]
88#[repr(u8)]
89#[non_exhaustive]
90pub enum Source {
91    PrimaryColor = ctru_sys::GPU_PRIMARY_COLOR,
92    FragmentPrimaryColor = ctru_sys::GPU_FRAGMENT_PRIMARY_COLOR,
93    FragmentSecondaryColor = ctru_sys::GPU_FRAGMENT_SECONDARY_COLOR,
94    Texture0 = ctru_sys::GPU_TEXTURE0,
95    Texture1 = ctru_sys::GPU_TEXTURE1,
96    Texture2 = ctru_sys::GPU_TEXTURE2,
97    Texture3 = ctru_sys::GPU_TEXTURE3,
98    PreviousBuffer = ctru_sys::GPU_PREVIOUS_BUFFER,
99    Constant = ctru_sys::GPU_CONSTANT,
100    Previous = ctru_sys::GPU_PREVIOUS,
101}
102
103/// The combination function to apply to the [`TexEnv`] operands.
104#[doc(alias = "GPU_COMBINEFUNC")]
105#[allow(missing_docs)]
106#[derive(Debug, Clone, Copy)]
107#[repr(u8)]
108#[non_exhaustive]
109pub enum CombineFunc {
110    Replace = ctru_sys::GPU_REPLACE,
111    Modulate = ctru_sys::GPU_MODULATE,
112    Add = ctru_sys::GPU_ADD,
113    AddSigned = ctru_sys::GPU_ADD_SIGNED,
114    Interpolate = ctru_sys::GPU_INTERPOLATE,
115    Subtract = ctru_sys::GPU_SUBTRACT,
116    Dot3Rgb = ctru_sys::GPU_DOT3_RGB,
117    // Added in libcrtu 2.3.0:
118    // Dot3Rgba = ctru_sys::GPU_DOT3_RGBA,
119}
120
121/// A texture combination stage identifier. This index doubles as the order
122/// in which texture combinations will be applied.
123// (I think?)
124#[derive(Copy, Clone, Debug)]
125pub struct Stage(pub(crate) usize);
126
127impl Stage {
128    /// Get a stage index. Valid indices range from 0 to 5.
129    pub fn new(index: usize) -> Option<Self> {
130        (index < 6).then_some(Self(index))
131    }
132}