#![deny(clippy::all, clippy::pedantic)] use std::ffi::CString; use std::process::abort; use glutin::context::{NotCurrentContext, PossiblyCurrentContext}; use glutin::display::GetGlDisplay; use glutin::prelude::{GlDisplay, NotCurrentGlContext, PossiblyCurrentGlContext}; use glutin::surface::{Surface, SurfaceTypeTrait}; pub mod buffer; pub mod data_types; pub mod debug; pub mod misc; pub mod shader; pub mod texture; pub mod vertex_array; pub struct ContextWithFns { context: PossiblyCurrentContext, fns: Box, } impl ContextWithFns { /// Returns a new `ContextWithFns`. /// /// # Errors /// Returns `Err` if making this context current fails. pub fn new( context: NotCurrentContext, surface: &Surface, ) -> Result { let context = context .make_current(surface) .map_err(Error::MakeContextCurrentFailed)?; let display = context.display(); let gl = sys::Gl::load_with(|symbol| { let Ok(symbol) = CString::new(symbol) else { eprintln!("GL symbol contains nul byte"); abort(); }; display.get_proc_address(&symbol) }); Ok(Self { context, fns: Box::new(gl) }) } /// Attempts to make this context current. /// /// # Errors /// Returns `Err` if making this context current fails. pub fn make_current( &self, surface: &Surface, ) -> Result, Error> { if !self.context.is_current() { self.context .make_current(surface) .map_err(Error::MakeContextCurrentFailed)?; } Ok(CurrentContextWithFns { ctx: self }) } #[must_use] pub fn context(&self) -> &PossiblyCurrentContext { &self.context } #[must_use] pub fn context_mut(&mut self) -> &mut PossiblyCurrentContext { &mut self.context } } pub struct CurrentContextWithFns<'ctx> { ctx: &'ctx ContextWithFns, } impl CurrentContextWithFns<'_> { #[inline] pub(crate) fn fns(&self) -> &sys::Gl { &self.ctx.fns } } #[derive(Debug, thiserror::Error)] pub enum Error { #[error("Failed to make context current")] MakeContextCurrentFailed(#[source] glutin::error::Error), } mod sys { #![allow( clippy::missing_safety_doc, clippy::missing_transmute_annotations, clippy::too_many_arguments, clippy::unused_unit, clippy::upper_case_acronyms, clippy::doc_markdown, clippy::unreadable_literal, unsafe_op_in_unsafe_fn )] include!(concat!(env!("OUT_DIR"), "/bindings.rs")); }