use std::ffi::c_int; use std::ptr::null_mut; use crate::util::is_main_thread; use crate::{get_glfw_error, Error}; /// GLFW 3.x.x is supported static SUPPORTED_GLFW_VERSION_MAJOR: c_int = 3; /// Initializes GLFW and returns a initialization token. /// /// # Errors /// Will return `Err` if /// - The current thread is not the main thread /// - A GLFW error occurs pub fn initialize() -> Result { if !is_main_thread() { return Err(Error::NotInMainThread); } let mut major: c_int = 0; unsafe { crate::ffi::glfwGetVersion(&mut major, null_mut(), null_mut()) }; if major != SUPPORTED_GLFW_VERSION_MAJOR { return Err(Error::UnsupportedVersion); } // SAFETY: The current thread is the main thread let success = unsafe { crate::ffi::glfwInit() }; if success == crate::ffi::GLFW_FALSE { get_glfw_error()?; } Ok(Glfw { _priv: &() }) } /// GLFW initialization token. #[derive(Debug)] pub struct Glfw { /// This field has two purposes /// - To make the struct not constructable without calling [`initialize`]. /// - To make the struct `!Send` and `!Sync`. _priv: *const (), } impl Drop for Glfw { fn drop(&mut self) { // SAFETY: The current thread cannot be any other thread than the main thread // since the initialize function checks it and the GLFW initialization token is // neither Send or Sync unsafe { crate::ffi::glfwTerminate() }; } }