egui_multiwin/
tracked_window.rs1use std::num::NonZeroU32;
4
5use egui::NumExt;
6use glutin::context::{NotCurrentContext, PossiblyCurrentContext};
7use glutin::prelude::GlDisplay;
8use glutin::prelude::{NotCurrentGlContext, PossiblyCurrentGlContext};
9use glutin::surface::GlSurface;
10use glutin::surface::WindowSurface;
11use thiserror::Error;
12use winit::event_loop::ControlFlow;
13
14pub struct ContextHolder<T> {
16 context: T,
18 pub window: winit::window::Window,
20 ws: glutin::surface::Surface<WindowSurface>,
22 display: glutin::display::Display,
24 options: TrackedWindowOptions,
26 pub control_flow: Option<ControlFlow>,
28}
29
30impl<T> ContextHolder<T> {
31 pub fn new(
33 context: T,
34 window: winit::window::Window,
35 ws: glutin::surface::Surface<WindowSurface>,
36 display: glutin::display::Display,
37 options: TrackedWindowOptions,
38 ) -> Self {
39 Self {
40 context,
41 window,
42 ws,
43 display,
44 options,
45 control_flow: Some(ControlFlow::Poll),
46 }
47 }
48}
49impl<T> ContextHolder<T> {
50 pub fn window(&self) -> &winit::window::Window {
52 &self.window
53 }
54}
55
56impl ContextHolder<PossiblyCurrentContext> {
57 pub fn swap_buffers(&self) -> glutin::error::Result<()> {
59 if self.options.vsync {
60 let _e = self.ws.set_swap_interval(
61 &self.context,
62 glutin::surface::SwapInterval::Wait(NonZeroU32::MIN),
63 );
64 } else {
65 let _e = self
66 .ws
67 .set_swap_interval(&self.context, glutin::surface::SwapInterval::DontWait);
68 }
69 self.ws.swap_buffers(&self.context)
70 }
71
72 pub fn resize(&self, size: winit::dpi::PhysicalSize<u32>) {
74 let w = size.width;
75 let h = size.height;
76 self.ws.resize(
77 &self.context,
78 NonZeroU32::new(w.at_least(1)).unwrap(),
79 NonZeroU32::new(h.at_least(1)).unwrap(),
80 )
81 }
82
83 pub fn make_current(&self) -> glutin::error::Result<()> {
85 self.context.make_current(&self.ws)
86 }
87
88 pub fn get_proc_address(&self, s: &str) -> *const std::ffi::c_void {
90 let cs: *const std::ffi::c_char = s.as_ptr().cast();
91 let cst = unsafe { std::ffi::CStr::from_ptr(cs) };
92 self.display.get_proc_address(cst)
93 }
94}
95
96impl ContextHolder<NotCurrentContext> {
97 pub fn make_current(
99 self,
100 ) -> Result<ContextHolder<PossiblyCurrentContext>, glutin::error::Error> {
101 let c = self.context.make_current(&self.ws).unwrap();
102 let s = ContextHolder::<PossiblyCurrentContext> {
103 context: c,
104 window: self.window,
105 ws: self.ws,
106 display: self.display,
107 options: self.options,
108 control_flow: self.control_flow,
109 };
110 Ok(s)
111 }
112}
113
114#[derive(Copy, Clone)]
116pub struct TrackedWindowOptions {
117 pub vsync: bool,
119 pub shader: Option<egui_glow::ShaderVersion>,
121}
122
123#[derive(Error, Debug)]
124pub enum DisplayCreationError {}