baseview 0.3.5

Low-level windowing system geared towards making audio plugin UIs.
Documentation
use crate::gl::GlConfig;
use crate::platform::gl::{CreationFailedError, FbConfig, FbConfigInner, WindowConfig};
use crate::platform::x11::xcb_window::XcbWindow;
use crate::platform::{PlatformError, X11Connection};
use crate::wrappers::egl::{Egl, EglConfig, EglContext, EglDisplay, EglSurface};
use std::ffi::{c_void, CStr};
use std::rc::Rc;
use x11rb::protocol::xproto::Visualid;

pub struct EglGlContext {
    surface: EglSurface,
    context: EglContext,
}

impl EglGlContext {
    pub(crate) fn create(
        window: &XcbWindow, gl_config: &GlConfig, egl_config: EglConfig, display: EglDisplay,
    ) -> Result<Self, PlatformError> {
        let surface = display.create_surface(egl_config, window.id().get(), gl_config)?;
        let context = display
            .egl()
            .with_opengl(|bound| display.create_context(egl_config, bound, gl_config))??;

        Ok(Self { surface, context })
    }
}

impl EglGlContext {
    pub fn get_fb_config_and_visual(
        connection: &Rc<X11Connection>, gl_config: GlConfig,
    ) -> Result<(FbConfig, WindowConfig), PlatformError> {
        let egl = Egl::open()?;
        let display = egl.create_display(connection)?;

        let config = display.choose_config(&gl_config)?.ok_or(CreationFailedError::EglNoDisplay)?;
        let visual = config.get_visual_id(&display)?;

        let depth = Self::find_visual_depth_for_id(connection, visual)
            .ok_or(CreationFailedError::EglUnknownVisualId(visual))?;

        let window_config = WindowConfig { depth, visual };
        let fb_config = FbConfig { gl_config, fb_config: FbConfigInner::Egl { display, config } };

        Ok((fb_config, window_config))
    }

    fn find_visual_depth_for_id(connection: &X11Connection, visual_id: Visualid) -> Option<u8> {
        connection
            .default_screen()
            .allowed_depths
            .iter()
            .find(|d| d.visuals.iter().any(|v| v.visual_id == visual_id))
            .map(|d| d.depth)
    }

    pub fn make_current(&self) -> Result<(), PlatformError> {
        self.context.make_current(&self.surface)?;

        Ok(())
    }

    pub fn make_not_current(&self) -> Result<(), PlatformError> {
        self.surface.display().egl().with_opengl(|gl| self.context.make_not_current(gl))??;

        Ok(())
    }

    pub fn get_proc_address(&self, symbol: &CStr) -> *const c_void {
        self.surface.display().egl().get_proc_address(symbol)
    }

    pub fn swap_buffers(&self) -> Result<(), PlatformError> {
        self.surface.swap_buffers()?;
        Ok(())
    }
}