baseview 0.3.5

Low-level windowing system geared towards making audio plugin UIs.
Documentation
use super::sys::*;
use super::*;
use crate::gl::GlConfig;
use std::ffi::c_void;
use std::ptr::NonNull;
use x11rb::protocol::xproto::Window;

pub struct EglSurface {
    display: EglDisplay,
    raw: NonNull<c_void>,
}

impl EglSurface {
    pub(super) fn create(
        display: &EglDisplay, config: EglConfig, window: Window, gl_config: &GlConfig,
    ) -> Result<EglSurface, EglError> {
        let raw = display.egl().create_surface(display, config, window, gl_config)?;

        Ok(Self { display: display.clone(), raw })
    }

    pub fn display(&self) -> &EglDisplay {
        &self.display
    }

    pub fn as_raw(&self) -> *mut c_void {
        self.raw.as_ptr()
    }

    pub fn swap_buffers(&self) -> Result<(), EglError> {
        self.display().egl().swap_buffers(self)
    }
}

impl Drop for EglSurface {
    fn drop(&mut self) {
        if let Err(e) = unsafe { self.display.egl().destroy_surface(self) } {
            crate::warn!("Failed to destroy EGL surface: {e}");
        }
    }
}

impl Egl {
    fn get_surface_attribs(gl_config: &GlConfig) -> [Int; 3] {
        #[rustfmt::skip]
        let fb_attribs = [
            EGL_GL_COLORSPACE, if gl_config.srgb { EGL_GL_COLORSPACE_SRGB } else { EGL_GL_COLORSPACE_LINEAR },
            // EGL_RENDER_BUFFER: EGL_BACK_BUFFER is default
            EGL_NONE,
        ];

        fb_attribs
    }

    fn create_surface(
        &self, display: &EglDisplay, config: EglConfig, window: Window, gl_config: &GlConfig,
    ) -> Result<NonNull<c_void>, EglError> {
        let attribs = Self::get_surface_attribs(gl_config);
        let result = unsafe {
            (self.inner.functions.eglCreateWindowSurface)(
                display.as_raw(),
                config.0.as_ptr(),
                window as _,
                attribs.as_ptr(),
            )
        };

        NonNull::new(result).ok_or_else(|| EglError::from_last_error(self))
    }

    fn swap_buffers(&self, surface: &EglSurface) -> Result<(), EglError> {
        let result = unsafe {
            (self.inner.functions.eglSwapBuffers)(surface.display().as_raw(), surface.as_raw())
        };

        if result == FALSE {
            Err(EglError::from_last_error(self))
        } else {
            Ok(())
        }
    }

    unsafe fn destroy_surface(&self, surface: &EglSurface) -> Result<(), EglError> {
        let result = unsafe {
            (self.inner.functions.eglDestroySurface)(surface.display().as_raw(), surface.as_raw())
        };

        if result == FALSE {
            Err(EglError::from_last_error(self))
        } else {
            Ok(())
        }
    }
}