use std::num::NonZeroU32;
use egui::NumExt;
use glutin::context::{NotCurrentContext, PossiblyCurrentContext};
use glutin::prelude::GlDisplay;
use glutin::prelude::{NotCurrentGlContext, PossiblyCurrentGlContext};
use glutin::surface::GlSurface;
use glutin::surface::WindowSurface;
use thiserror::Error;
use winit::event_loop::ControlFlow;
pub struct ContextHolder<T> {
context: T,
pub window: winit::window::Window,
ws: glutin::surface::Surface<WindowSurface>,
display: glutin::display::Display,
options: TrackedWindowOptions,
pub control_flow: Option<ControlFlow>,
}
impl<T> ContextHolder<T> {
pub fn new(
context: T,
window: winit::window::Window,
ws: glutin::surface::Surface<WindowSurface>,
display: glutin::display::Display,
options: TrackedWindowOptions,
) -> Self {
Self {
context,
window,
ws,
display,
options,
control_flow: Some(ControlFlow::Poll),
}
}
}
impl<T> ContextHolder<T> {
pub fn window(&self) -> &winit::window::Window {
&self.window
}
}
impl ContextHolder<PossiblyCurrentContext> {
pub fn swap_buffers(&self) -> glutin::error::Result<()> {
if self.options.vsync {
let _e = self.ws.set_swap_interval(
&self.context,
glutin::surface::SwapInterval::Wait(NonZeroU32::MIN),
);
} else {
let _e = self
.ws
.set_swap_interval(&self.context, glutin::surface::SwapInterval::DontWait);
}
self.ws.swap_buffers(&self.context)
}
pub fn resize(&self, size: winit::dpi::PhysicalSize<u32>) {
let w = size.width;
let h = size.height;
self.ws.resize(
&self.context,
NonZeroU32::new(w.at_least(1)).unwrap(),
NonZeroU32::new(h.at_least(1)).unwrap(),
)
}
pub fn make_current(&self) -> glutin::error::Result<()> {
self.context.make_current(&self.ws)
}
pub fn get_proc_address(&self, s: &str) -> *const std::ffi::c_void {
let cs: *const std::ffi::c_char = s.as_ptr().cast();
let cst = unsafe { std::ffi::CStr::from_ptr(cs) };
self.display.get_proc_address(cst)
}
}
impl ContextHolder<NotCurrentContext> {
pub fn make_current(
self,
) -> Result<ContextHolder<PossiblyCurrentContext>, glutin::error::Error> {
let c = self.context.make_current(&self.ws).unwrap();
let s = ContextHolder::<PossiblyCurrentContext> {
context: c,
window: self.window,
ws: self.ws,
display: self.display,
options: self.options,
control_flow: self.control_flow,
};
Ok(s)
}
}
#[derive(Copy, Clone)]
pub struct TrackedWindowOptions {
pub vsync: bool,
pub shader: Option<egui_glow::ShaderVersion>,
}
#[derive(Error, Debug)]
pub enum DisplayCreationError {}