From f255db0f9252f4041b120dcaa00470889c4cb9f4 Mon Sep 17 00:00:00 2001 From: HampusM Date: Fri, 6 Oct 2023 20:55:07 +0200 Subject: feat: add GLFW wrapper library --- glfw/src/window.rs | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 glfw/src/window.rs (limited to 'glfw/src/window.rs') diff --git a/glfw/src/window.rs b/glfw/src/window.rs new file mode 100644 index 0000000..6f5c845 --- /dev/null +++ b/glfw/src/window.rs @@ -0,0 +1,128 @@ +use std::ffi::{CStr, CString}; +use std::ptr::null_mut; + +use crate::init::{initialize, Glfw}; +use crate::{get_glfw_error, Error}; + +pub struct Window +{ + _init: Glfw, + handle: *mut crate::ffi::GLFWwindow, +} + +impl Window +{ + /// Creates a new window. + /// + /// # Errors + /// Will return `Err` if + /// - The title contains an internal nul byte + /// - A GLFW error occurs + pub fn create(size: &Size, title: &str) -> Result + { + let init = initialize()?; + + let c_title = + CString::new(title).map_err(|_| Error::InternalNulByteInWindowTitle)?; + + // SAFETY: The initialize function makes sure the current thread is the main + // thread + let handle = unsafe { + #[allow(clippy::cast_possible_wrap)] + crate::ffi::glfwCreateWindow( + size.width as i32, + size.height as i32, + c_title.as_ptr(), + null_mut(), + null_mut(), + ) + }; + + get_glfw_error()?; + + Ok(Self { + _init: init, + handle, + }) + } + + /// Makes the context of the window current for the calling thread. + /// + /// # Errors + /// Will return `Err` if a GLFW platform error occurs or if no OpenGL context is + /// present. + pub fn make_context_current(&self) -> Result<(), Error> + { + unsafe { crate::ffi::glfwMakeContextCurrent(self.handle) }; + + get_glfw_error()?; + + Ok(()) + } + + /// Returns the address of the specified OpenGL function, if it is supported by the + /// current context. + /// + /// # Errors + /// Will return `Err` if a GLFW platform error occurs or if no current context has + /// been set. + pub fn get_proc_address( + &self, + proc_name: &CStr, + ) -> Result + { + let proc_addr = unsafe { crate::ffi::glfwGetProcAddress(proc_name.as_ptr()) }; + + get_glfw_error()?; + + // SAFETY: Is only None when a error has occured and that case is handled above + Ok(unsafe { proc_addr.unwrap_unchecked() }) + } + + /// Processes all pending events. + /// + /// # Errors + /// Will return `Err` if a GLFW platform error occurs. + pub fn poll_events(&self) -> Result<(), Error> + { + // SAFETY: The initialize function (called when the window is created) makes sure + // the current thread is the main thread + unsafe { crate::ffi::glfwPollEvents() }; + + get_glfw_error()?; + + Ok(()) + } + + /// Swaps the front and back buffers of the window. + /// + /// # Errors + /// Will return `Err` if a GLFW platform error occurs or if no OpenGL window context + /// is present. + pub fn swap_buffers(&self) -> Result<(), Error> + { + unsafe { + crate::ffi::glfwSwapBuffers(self.handle); + }; + + get_glfw_error()?; + + Ok(()) + } + + /// Returns whether or not the window should close. + #[must_use] + pub fn should_close(&self) -> bool + { + let should_close = unsafe { crate::ffi::glfwWindowShouldClose(self.handle) }; + + should_close == crate::ffi::GLFW_TRUE + } +} + +/// Window size. +pub struct Size +{ + pub width: u32, + pub height: u32, +} -- cgit v1.2.3-18-g5258