glfw/
lib.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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
//! This crate provides a statically-linked definition of the GLFW library
//! from source.
//!
//! The generated bindings are
#![deny(missing_docs)]
#![deny(unused_results)]
#![deny(rust_2018_idioms)]

// GLFW carries a synthetic dependency to OpenGL. It's not technically required
// for the library to function, but it's a logical requirement for the library.
#[cfg(feature = "opengl")]
use gl as _;

pub mod c {
  #![allow(non_upper_case_globals)]
  #![allow(non_camel_case_types)]
  #![allow(non_snake_case)]
  #![allow(unused)]
  #![allow(missing_docs)]
  #![allow(unused_results)]
  #![allow(rust_2018_idioms)]
  #![allow(rustdoc::broken_intra_doc_links)]
  #![allow(clippy::all)]
  #[doc(inline)]
  pub use glfw_sys::*;
}

/// An error that may be returned from a GLFW operation.
///
/// These correspond 1:1 with
#[derive(Debug)]
pub enum Error {
  /// An error returned when GLFW has not been initialized.
  NotInitialized,

  /// An error returned when the current context is incorrect.
  NoCurrentContext,

  /// An error returned when an enumerated value is out of the range of valid
  /// inputs.
  InvalidEnum,

  /// An error returned when a value is outsode fh te range of valid inputs.
  InvalidValue,

  /// An error returned if GLFW runs out of memory.
  OutOfMemory,

  /// An error returned if an API has been disabled or is unavailable
  ApiUnavailable,

  /// An error returned if an API is available, but a specific version is
  /// unavailable (such as the OpenGL version)
  VersionUnavailable,

  /// A generic platform-specific error has occurred.
  PlatformError,

  /// A specific format is unavailable.
  FormatUnavailable,

  /// An error that occurs when no window context is available.
  NoWindowContext,

  /// An error outside of this enumeration has occurred.
  /// If this shows up, it means GLFW either didn't document an error-code, or
  /// it has added a new error code in an update.
  Unknown(core::ffi::c_int),
}

impl std::fmt::Display for Error {
  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    match self {
      Error::NotInitialized => "",
      Error::NoCurrentContext => "",
      Error::InvalidEnum => "",
      Error::InvalidValue => "",
      Error::OutOfMemory => "",
      Error::ApiUnavailable => "",
      Error::VersionUnavailable => "",
      Error::PlatformError => "",
      Error::FormatUnavailable => "",
      Error::NoWindowContext => "",
      Error::Unknown(_) => "",
    }
    .fmt(f)
  }
}

impl std::error::Error for Error {}

impl Error {
  /// Constructs this Error from a GLFW status value.
  ///
  /// # Parameters
  ///
  /// * `code` - the GLFW status code
  pub fn from_glfw_status(code: core::ffi::c_int) -> Self {
    match code as u32 {
      c::GLFW_NOT_INITIALIZED => Self::NotInitialized,
      c::GLFW_NO_CURRENT_CONTEXT => Self::NoCurrentContext,
      c::GLFW_INVALID_ENUM => Self::InvalidEnum,
      c::GLFW_INVALID_VALUE => Self::InvalidValue,
      c::GLFW_OUT_OF_MEMORY => Self::OutOfMemory,
      c::GLFW_API_UNAVAILABLE => Self::ApiUnavailable,
      c::GLFW_VERSION_UNAVAILABLE => Self::VersionUnavailable,
      c::GLFW_PLATFORM_ERROR => Self::PlatformError,
      c::GLFW_FORMAT_UNAVAILABLE => Self::FormatUnavailable,
      c::GLFW_NO_WINDOW_CONTEXT => Self::NoWindowContext,
      _ => Self::Unknown(code),
    }
  }
}

/// A specialized [`Result`] type for GLFW operations.
///
/// [`Result`]: std::result::Result
pub type Result<T> = std::result::Result<T, Error>;

/// An instance of the GLFW context, of which there should only ever be at most
/// one of.
pub struct Instance;

impl Instance {
  /// Constructs a new [`Instance`] object and returns the instance.
  pub fn new() -> Result<Self> {
    if unsafe { c::glfwInit() } == (c::GLFW_TRUE as core::ffi::c_int) {
      Ok(Instance)
    } else {
      Err(Error::from_glfw_status(unsafe {
        c::glfwGetError(std::ptr::null_mut())
      }))
    }
  }

  /// Polls the [`Instance`] for events.
  ///
  /// This calls [`glfwPollEvents`] implicitly
  ///
  /// [`glfwPollEvents`]: https://www.glfw.org/docs/3.3/group__window.html#ga37bd57223967b4211d60ca1a0bf3c832
  pub fn poll_events(&self) {
    unsafe { c::glfwPollEvents() }
  }

  /// Queries whether this [`Instance`] supports the Vulkan API.
  pub fn vulkan_supported(&self) -> bool {
    unsafe { c::glfwVulkanSupported() != 0 }
  }
}

impl Drop for Instance {
  fn drop(&mut self) {
    unsafe { c::glfwTerminate() };
  }
}

/// A wrapper type around [`GLFWwindow`].
///
/// [`GLFWwindow`]: c::GLFWwindow
pub struct Window(*mut c::GLFWwindow);

impl Window {
  /// Constructs this [`Window`] from an underlying [`c::GLFWwindow`] instance.
  ///
  /// This will panic if `window` is `null`.
  #[inline]
  pub fn from_c(window: *mut c::GLFWwindow) -> Self {
    debug_assert!(!window.is_null());
    Self(window)
  }

  /// Makes this window's context current.
  ///
  /// For more details, see [`glfwMakeContextCurrent`].
  ///
  /// [`glfwMakeContextCurrent`]: https://www.glfw.org/docs/3.3/group__context.html#gad94e80185397a6cf5fe2ab30567af71c
  pub fn make_context_current(&self) {
    unsafe { c::glfwMakeContextCurrent(self.0) }
  }

  /// Queries whether this Window should be closed.
  #[inline]
  pub fn should_close(&self) -> bool {
    unsafe { c::glfwWindowShouldClose(self.0) != 0 }
  }

  /// Gets a constant pointer to the underlying [`c::GLFWwindow`].
  pub fn ptr(&self) -> *const c::GLFWwindow {
    self.0
  }

  /// Gets a mutable pointer to the underlying [`c::GLFWwindow`].
  pub fn ptr_mut(&self) -> *mut c::GLFWwindow {
    self.0
  }

  /// Shows this window.
  #[inline]
  pub fn show(&self) {
    unsafe { c::glfwShowWindow(self.0) }
  }

  /// Swaps the underlying buffers of this window.
  #[inline]
  pub fn swap_buffers(&self) {
    unsafe { c::glfwSwapBuffers(self.0) }
  }
}

impl Drop for Window {
  fn drop(&mut self) {
    unsafe { c::glfwDestroyWindow(self.0) }
  }
}