//! Glium compatibility module use backend::graphics::{gl::GLGraphicsBackend, SwapBuffersError}; use glium::{ backend::{Backend, Context, Facade}, debug::DebugCallbackBehavior, Frame, SwapBuffersError as GliumSwapBuffersError, }; use std::{ cell::{Ref, RefCell, RefMut}, os::raw::c_void, rc::Rc, }; impl From for GliumSwapBuffersError { fn from(error: SwapBuffersError) -> Self { match error { SwapBuffersError::ContextLost => GliumSwapBuffersError::ContextLost, SwapBuffersError::AlreadySwapped => GliumSwapBuffersError::AlreadySwapped, SwapBuffersError::Unknown(_) => GliumSwapBuffersError::ContextLost, // TODO } } } /// Wrapper to expose `Glium` compatibility pub struct GliumGraphicsBackend { context: Rc, backend: Rc>, } struct InternalBackend(RefCell); impl GliumGraphicsBackend { fn new(backend: T) -> GliumGraphicsBackend { let internal = Rc::new(InternalBackend(RefCell::new(backend))); GliumGraphicsBackend { // cannot fail context: unsafe { Context::new(internal.clone(), true, DebugCallbackBehavior::default()).unwrap() }, backend: internal, } } /// Start drawing on the backbuffer. /// /// This function returns a `Frame`, which can be used to draw on it. When the `Frame` is /// destroyed, the buffers are swapped. /// /// Note that destroying a `Frame` is immediate, even if vsync is enabled. #[inline] pub fn draw(&self) -> Frame { Frame::new(self.context.clone(), self.backend.get_framebuffer_dimensions()) } /// Borrow the underlying backend. /// /// This follows the same semantics as `std::cell:RefCell`. /// Multiple read-only borrows are possible. Borrowing the /// backend while there is a mutable reference will panic. pub fn borrow(&self) -> Ref { self.backend.0.borrow() } /// Borrow the underlying backend mutably. /// /// This follows the same semantics as `std::cell:RefCell`. /// Holding any other borrow while trying to borrow the backend /// mutably will panic. Note that Glium will borrow the backend /// (not mutably) during rendering. pub fn borrow_mut(&self) -> RefMut { self.backend.0.borrow_mut() } } impl Facade for GliumGraphicsBackend { fn get_context(&self) -> &Rc { &self.context } } impl From for GliumGraphicsBackend { fn from(backend: T) -> Self { GliumGraphicsBackend::new(backend) } } unsafe impl Backend for InternalBackend { fn swap_buffers(&self) -> Result<(), GliumSwapBuffersError> { self.0.borrow().swap_buffers().map_err(Into::into) } unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void { self.0.borrow().get_proc_address(symbol) as *const c_void } fn get_framebuffer_dimensions(&self) -> (u32, u32) { self.0.borrow().get_framebuffer_dimensions() } fn is_current(&self) -> bool { self.0.borrow().is_current() } unsafe fn make_current(&self) { self.0.borrow().make_current().expect("Context was lost") } }