use winit::event_loop::EventLoop;
use glium::Surface;
use glutin::surface::WindowSurface;
use glutin::config::ConfigTemplateBuilder;
use glutin::context::{ContextApi, ContextAttributesBuilder};
use glutin::display::GetGlDisplay;
use glutin::prelude::*;
use glutin::surface::SurfaceAttributesBuilder;
use glutin_winit::DisplayBuilder;
use raw_window_handle::HasWindowHandle;
use takeable_option::Takeable;
use std::ffi::CString;
use std::rc::Rc;
use std::cell::RefCell;
use std::num::NonZeroU32;
use std::os::raw::c_void;
fn main() {
let event_loop = EventLoop::builder()
.build()
.expect("event loop building");
let window_attributes = winit::window::Window::default_attributes();
let config_template_builder = ConfigTemplateBuilder::new();
let display_builder = DisplayBuilder::new().with_window_attributes(Some(window_attributes));
let (window, gl_config) = display_builder
.build(&event_loop, config_template_builder, |mut configs| {
configs.next().unwrap()
})
.unwrap();
let window = window.unwrap();
let window_handle = window.window_handle().unwrap();
let context_attributes = ContextAttributesBuilder::new().build(Some(window_handle.into()));
let fallback_context_attributes = ContextAttributesBuilder::new()
.with_context_api(ContextApi::Gles(None))
.build(Some(window_handle.into()));
let not_current_gl_context = Some(unsafe {
gl_config.display().create_context(&gl_config, &context_attributes).unwrap_or_else(|_| {
gl_config.display()
.create_context(&gl_config, &fallback_context_attributes)
.expect("failed to create context")
})
});
let (width, height): (u32, u32) = window.inner_size().into();
let attrs = SurfaceAttributesBuilder::<WindowSurface>::new().build(
window_handle.into(),
NonZeroU32::new(width).unwrap(),
NonZeroU32::new(height).unwrap(),
);
let surface = unsafe { gl_config.display().create_window_surface(&gl_config, &attrs).unwrap() };
let context = not_current_gl_context.unwrap().make_current(&surface).unwrap();
let gl_window = Rc::new(RefCell::new(Takeable::new((context, surface))));
struct Backend {
gl_window: Rc<RefCell<Takeable<(glutin::context::PossiblyCurrentContext, glutin::surface::Surface<WindowSurface>)>>>,
}
unsafe impl glium::backend::Backend for Backend {
fn swap_buffers(&self) -> Result<(), glium::SwapBuffersError> {
let gl_window = self.gl_window.borrow();
match gl_window.1.swap_buffers(&gl_window.0) {
Ok(()) => Ok(()),
Err(glutin::error::Error {..}) => Err(glium::SwapBuffersError::ContextLost),
}
}
unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void {
let symbol = CString::new(symbol).unwrap();
self.gl_window.borrow().0.display().get_proc_address(&symbol) as *const _
}
fn get_framebuffer_dimensions(&self) -> (u32, u32) {
let window = &self.gl_window.borrow().1;
(window.width().unwrap(), window.height().unwrap())
}
fn resize(&self, new_size:(u32, u32)) {
let pair = &self.gl_window.borrow();
let context = &pair.0;
let window = &pair.1;
window.resize(context, NonZeroU32::new(new_size.0).unwrap(), NonZeroU32::new(new_size.1).unwrap());
}
fn is_current(&self) -> bool {
self.gl_window.borrow().0.is_current()
}
unsafe fn make_current(&self) {
let mut gl_window_takeable = self.gl_window.borrow_mut();
let gl_window = Takeable::take(&mut gl_window_takeable);
gl_window.0.make_current(&gl_window.1).unwrap();
Takeable::insert(&mut gl_window_takeable, gl_window);
}
}
let context = unsafe {
let backend = Backend { gl_window: gl_window };
glium::backend::Context::new(backend, true, Default::default())
}.unwrap();
let mut target = glium::Frame::new(context.clone(), context.get_framebuffer_dimensions());
target.clear_color(0.0, 1.0, 0.0, 1.0);
target.finish().unwrap();
#[allow(deprecated)]
event_loop.run(|event, window_target| {
match event {
glium::winit::event::Event::WindowEvent { event, .. } => match event {
glium::winit::event::WindowEvent::CloseRequested => window_target.exit(),
_ => (),
},
_ => (),
}
})
.unwrap();
}