gl/
cull.rs

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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use crate::error::Result;

use super::Capability;

/// An enumeration of the face to cull
#[derive(Copy, Clone, Debug)]
pub enum CullFace {
  /// Cull the front face
  Front = crate::c::FRONT as isize,
  /// Cull the back face
  Back = crate::c::BACK as isize,
  /// Cull both the front and back face
  FrontAndBack = crate::c::FRONT_AND_BACK as isize,
}

impl std::fmt::Display for CullFace {
  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    match self {
      Self::Front => "Front",
      Self::Back => "Back",
      Self::FrontAndBack => "FrontAndBack",
    }
    .fmt(f)
  }
}

impl CullFace {
  /// Returns the face from the given enumeration
  ///
  /// # Parameters
  ///
  /// * `e` - The enumeration to get the face from
  pub const fn from_enum(e: crate::c::GLenum) -> Option<Self> {
    match e {
      crate::c::FRONT => Some(Self::Front),
      crate::c::BACK => Some(Self::Back),
      crate::c::FRONT_AND_BACK => Some(Self::FrontAndBack),
      _ => None,
    }
  }

  /// Returns the face from the given enumeration without checking
  ///
  /// # Parameters
  ///
  /// * `e` - The enumeration to get the face from
  ///
  /// # Safety
  ///
  /// The enumeration must be one of the valid faces
  pub const unsafe fn from_enum_unchecked(e: crate::c::GLenum) -> Self {
    match e {
      crate::c::FRONT => Self::Front,
      crate::c::BACK => Self::Back,
      crate::c::FRONT_AND_BACK => Self::FrontAndBack,
      _ => unreachable!(),
    }
  }

  /// Returns the value of the face
  #[inline]
  pub const fn value(self) -> crate::c::GLenum {
    self as crate::c::GLenum
  }
}

/// Enables polygon culling.
#[inline(always)]
pub fn enable_cull_face() {
  Capability::CullFace.enable();
}

/// Disables polygon culling.
#[inline(always)]
pub fn disable_cull_face() {
  Capability::CullFace.disable();
}

/// Toggles polygon culling.
#[inline(always)]
pub fn toggle_cull_face() {
  Capability::CullFace.toggle();
}

/// Specifies which face to cull (front, back, or both)
///
/// # Parameters
///
/// * `face` - The face to cull
#[inline]
pub fn set_cull_face(face: CullFace) {
  unsafe { crate::c::glCullFace(face as u32) }
}

/// Specifies which face to cull (front, back, or both), and checks for errors.
///
/// This is a convenience-wrapper around [`set_cull_face`] and
/// [`crate::gl::error::check`].
///
/// # Parameters
///
/// * `face` - The face to cull
#[inline]
pub fn set_cull_face_checked(face: CullFace) -> Result<()> {
  crate::error::check(|| set_cull_face(face))
}

/// Queries whether whether polygon culling is enabled.
#[inline(always)]
pub fn is_cull_face_enabled() -> bool {
  Capability::CullFace.is_enabled()
}

/// Returns the current face to cull.
///
/// If face culling is disabled, returns [`None`]
pub fn cull_face() -> Option<CullFace> {
  if !is_cull_face_enabled() {
    None
  } else {
    Some(unsafe { cull_face_unchecked() })
  }
}

/// Returns the current face to cull without checking if cull face is enabled.
///
/// # Safety
///
/// The cull face must be enabled.
#[inline]
pub unsafe fn cull_face_unchecked() -> CullFace {
  let mut value = 0;
  unsafe {
    crate::c::glGetIntegerv(crate::c::CULL_FACE_MODE, &mut value);
  }
  unsafe { CullFace::from_enum_unchecked(value as crate::c::GLenum) }
}