crispy/raw.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
/*
* SPDX-FileCopyrightText: 2022 Purism, SPC <https://puri.sm>
*
* SPDX-License-Identifier: MPL-2.0 OR LGPL-2.1-or-later
*/
/*! Minimal glium backend. Tested with EGL+gbm context. */
use crate::egl::headless::{ContextRef, EglContext};
use std::cell::RefCell;
use std::ffi::c_void;
use std::rc::Rc;
/// A simple backend for rendering into GBM (headless) buffers used via an EGL context.
///
/// Contrary to a typical backend (?), this one does not assume a default buffer. It's meant to be used to draw to random surfaces. (TODO: is there a reason to attach it to every GBM surface?).
///
/// Not very safe. Do your own swapbuffers.
/// Prints debug info.
pub struct Backend{
ctx: ContextRef, // This could possibly accommodate any kind of EGL context, but we focus on the simple case for now
size: Rc<RefCell<(u32, u32)>>,
}
impl Backend {
fn new(ctx: ContextRef, size: (u32, u32)) -> Self {
Backend { ctx, size: Rc::new(RefCell::new(size)) }
}
pub unsafe fn get_proc_address(name: &str) -> *const c_void {
ContextRef::get_proc_address(name)
}
}
unsafe impl glium::backend::Backend for Backend {
fn swap_buffers(&self) -> Result<(), glium::SwapBuffersError> { Ok(()) }
unsafe fn get_proc_address(&self, name: &str) -> *const c_void {
Backend::get_proc_address(name)
}
fn get_framebuffer_dimensions(&self) -> (u32, u32) {
let _ = *self.size.borrow();
unimplemented!("There is no default framebuffer. Use an explicit surface.");
}
fn is_current(&self) -> bool { false }
unsafe fn make_current(&self) {
unsafe { self.ctx.force_make_current() }
}
fn resize(&self, new_size:(u32, u32)) {
*self.size.borrow_mut() = new_size;
unimplemented!("There is no default framebuffer. Use an explicit surface.");
}
}
/// The context for glium operations.
/// For EGL operations, use the EGL context directly.
pub struct Facade {
ctx: Rc<glium::backend::Context>,
egl: ContextRef,
}
impl glium::backend::Facade for Facade {
fn get_context(&self) -> &Rc<glium::backend::Context> { &self.ctx }
}
impl Facade {
pub fn new(ctx: ContextRef, size: (u32, u32)) -> Self {
Self {
ctx: {
// Backend::new calls Backend::make_current, but we pretend w don't know it.
let _current_lock = ctx.make_current();
unsafe {
glium::backend::Context::new(
Backend::new(ctx.clone(), size),
false,
glium::debug::DebugCallbackBehavior::PrintAll
)
}.unwrap()
},
egl: ctx,
}
}
pub fn get_egl_context(&self) -> &ContextRef {
&self.egl
}
// TODO: does the size even matter for this use case?
// The size describes the default frame buffer.
// We don't have and never write to the default frame buffer, after all.
pub fn new_unsized(ctx: ContextRef) -> Self {
Self::new(ctx, (0, 0))
}
}