use {Frame, IncompatibleOpenGl, SwapBuffersError};
use debug;
use context;
use backend::{self, Backend};
use std::rc::Rc;
use std::cell::RefCell;
use std::ops::Deref;
use std::os::raw::c_void;
use super::glutin;
use super::glutin::{PossiblyCurrent as Pc, ContextCurrentState};
use takeable_option::Takeable;
pub struct Headless {
context: Rc<context::Context>,
glutin: Rc<RefCell<Takeable<glutin::Context<Pc>>>>,
}
pub struct GlutinBackend(Rc<RefCell<Takeable<glutin::Context<Pc>>>>);
impl Deref for Headless {
type Target = context::Context;
fn deref(&self) -> &context::Context {
&self.context
}
}
impl Deref for GlutinBackend {
type Target = Rc<RefCell<Takeable<glutin::Context<Pc>>>>;
fn deref(&self) -> &Rc<RefCell<Takeable<glutin::Context<Pc>>>> {
&self.0
}
}
unsafe impl Backend for GlutinBackend {
#[inline]
fn swap_buffers(&self) -> Result<(), SwapBuffersError> {
Ok(())
}
#[inline]
unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void {
self.0.borrow().get_proc_address(symbol) as *const _
}
#[inline]
fn get_framebuffer_dimensions(&self) -> (u32, u32) {
(800, 600) }
#[inline]
fn is_current(&self) -> bool {
self.0.borrow().is_current()
}
#[inline]
unsafe fn make_current(&self) {
let mut gl_window_takeable = self.0.borrow_mut();
let gl_window = Takeable::take(&mut gl_window_takeable);
let gl_window_new = gl_window.make_current().unwrap();
Takeable::insert(&mut gl_window_takeable, gl_window_new);
}
}
impl backend::Facade for Headless {
#[inline]
fn get_context(&self) -> &Rc<context::Context> {
&self.context
}
}
impl Headless {
pub fn new<T: ContextCurrentState>(context: glutin::Context<T>) -> Result<Self, IncompatibleOpenGl> {
Self::with_debug(context, Default::default())
}
pub unsafe fn unchecked<T: ContextCurrentState>(context: glutin::Context<T>) -> Result<Self, IncompatibleOpenGl> {
Self::unchecked_with_debug(context, Default::default())
}
pub fn with_debug<T: ContextCurrentState>(context: glutin::Context<T>, debug: debug::DebugCallbackBehavior)
-> Result<Self, IncompatibleOpenGl>
{
Self::new_inner(context, debug, true)
}
pub unsafe fn unchecked_with_debug<T: ContextCurrentState>(
context: glutin::Context<T>,
debug: debug::DebugCallbackBehavior,
) -> Result<Self, IncompatibleOpenGl>
{
Self::new_inner(context, debug, false)
}
fn new_inner<T: ContextCurrentState>(
context: glutin::Context<T>,
debug: debug::DebugCallbackBehavior,
checked: bool,
) -> Result<Self, IncompatibleOpenGl>
{
let context = unsafe {
context.treat_as_current()
};
let glutin_context = Rc::new(RefCell::new(Takeable::new(context)));
let glutin_backend = GlutinBackend(glutin_context.clone());
let context = unsafe { context::Context::new(glutin_backend, checked, debug) }?;
Ok(Headless { context: context, glutin: glutin_context })
}
#[inline]
pub fn draw(&self) -> Frame {
Frame::new(self.context.clone(), self.get_framebuffer_dimensions())
}
}