diff options
Diffstat (limited to 'opengl-bindings/src/lib.rs')
| -rw-r--r-- | opengl-bindings/src/lib.rs | 119 | 
1 files changed, 119 insertions, 0 deletions
diff --git a/opengl-bindings/src/lib.rs b/opengl-bindings/src/lib.rs new file mode 100644 index 0000000..7fd9933 --- /dev/null +++ b/opengl-bindings/src/lib.rs @@ -0,0 +1,119 @@ +#![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<sys::Gl>, +} + +impl ContextWithFns +{ +    /// Returns a new `ContextWithFns`. +    /// +    /// # Errors +    /// Returns `Err` if making this context current fails. +    pub fn new<SurfaceType: SurfaceTypeTrait>( +        context: NotCurrentContext, +        surface: &Surface<SurfaceType>, +    ) -> Result<Self, Error> +    { +        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<SurfaceType: SurfaceTypeTrait>( +        &self, +        surface: &Surface<SurfaceType>, +    ) -> Result<CurrentContextWithFns<'_>, 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")); +}  | 
