egui_glow: update example to latest glutin (#2396)
This lifts the context handling from commit hash 8eb687c
as this does
all the required handling for us that the older glutin once did.
This commit is contained in:
parent
32144d3cb9
commit
be4a5be145
3 changed files with 159 additions and 47 deletions
21
Cargo.lock
generated
21
Cargo.lock
generated
|
@ -1306,7 +1306,7 @@ dependencies = [
|
|||
"egui-winit",
|
||||
"egui_glow",
|
||||
"glow",
|
||||
"glutin 0.30.0",
|
||||
"glutin 0.30.2",
|
||||
"image",
|
||||
"js-sys",
|
||||
"percent-encoding",
|
||||
|
@ -1445,9 +1445,10 @@ dependencies = [
|
|||
"egui",
|
||||
"egui-winit",
|
||||
"glow",
|
||||
"glutin 0.29.1",
|
||||
"glutin 0.30.2",
|
||||
"memoffset",
|
||||
"puffin",
|
||||
"raw-window-handle 0.5.0",
|
||||
"tracing",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
|
@ -1969,23 +1970,23 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "glutin"
|
||||
version = "0.30.0"
|
||||
version = "0.30.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34acbf502536f1d125f0fc09b6ad8824e93e6da7b99e86d3383e6b8310ba3554"
|
||||
checksum = "0282c380a3adb52ae095e5847cc575c6bf79d296dcbf333e00be4a3fca07235e"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg_aliases",
|
||||
"cgl",
|
||||
"cocoa",
|
||||
"core-foundation",
|
||||
"glutin_egl_sys 0.3.0",
|
||||
"glutin_egl_sys 0.3.1",
|
||||
"glutin_glx_sys 0.3.0",
|
||||
"glutin_wgl_sys 0.3.0",
|
||||
"libloading",
|
||||
"objc",
|
||||
"once_cell",
|
||||
"raw-window-handle 0.5.0",
|
||||
"wayland-sys 0.30.0-beta.12",
|
||||
"wayland-sys 0.30.0",
|
||||
"windows-sys 0.36.1",
|
||||
"x11-dl",
|
||||
]
|
||||
|
@ -2002,9 +2003,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "glutin_egl_sys"
|
||||
version = "0.3.0"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c3c95a2d7a54bab0c74759794efb5cd63470d4504cbe85ed4114dc82c98bdc1"
|
||||
checksum = "3adbb8fec0e18e340f990c78f79f5f0e142d0d83f46b10909aaa7d251c00afdf"
|
||||
dependencies = [
|
||||
"gl_generator",
|
||||
"windows-sys 0.36.1",
|
||||
|
@ -4460,9 +4461,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wayland-sys"
|
||||
version = "0.30.0-beta.12"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1117fe4570fe063122ba2b1b1e39e56fb1a73921d395f9288af06af0dd1c7f55"
|
||||
checksum = "8bcdbc325d8a78a9f49dcb77b39e92656e93b3f69eb4d60245f2116ec4bb0a97"
|
||||
dependencies = [
|
||||
"dlib",
|
||||
"lazy_static",
|
||||
|
|
|
@ -72,7 +72,8 @@ wasm-bindgen = { version = "0.2" }
|
|||
|
||||
|
||||
[dev-dependencies]
|
||||
glutin = "0.29.0" # examples/pure_glow
|
||||
glutin = "0.30.2" # examples/pure_glow
|
||||
raw-window-handle = "0.5.0"
|
||||
|
||||
|
||||
[[example]]
|
||||
|
|
|
@ -3,10 +3,124 @@
|
|||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
#![allow(unsafe_code)]
|
||||
|
||||
use egui_winit::winit;
|
||||
|
||||
/// The majority of `GlutinWindowContext` is taken from `eframe`
|
||||
struct GlutinWindowContext {
|
||||
window: winit::window::Window,
|
||||
gl_context: glutin::context::PossiblyCurrentContext,
|
||||
gl_display: glutin::display::Display,
|
||||
gl_surface: glutin::surface::Surface<glutin::surface::WindowSurface>,
|
||||
}
|
||||
|
||||
impl GlutinWindowContext {
|
||||
// refactor this function to use `glutin-winit` crate eventually.
|
||||
// preferably add android support at the same time.
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn new(winit_window: winit::window::Window) -> Self {
|
||||
use glutin::prelude::*;
|
||||
use raw_window_handle::*;
|
||||
|
||||
let raw_display_handle = winit_window.raw_display_handle();
|
||||
let raw_window_handle = winit_window.raw_window_handle();
|
||||
|
||||
// EGL is crossplatform and the official khronos way
|
||||
// but sometimes platforms/drivers may not have it, so we use back up options where possible.
|
||||
|
||||
// try egl and fallback to windows wgl. Windows is the only platform that *requires* window handle to create display.
|
||||
#[cfg(target_os = "windows")]
|
||||
let preference = glutin::display::DisplayApiPreference::EglThenWgl(Some(window_handle));
|
||||
// try egl and fallback to x11 glx
|
||||
#[cfg(target_os = "linux")]
|
||||
let preference = glutin::display::DisplayApiPreference::EglThenGlx(Box::new(
|
||||
winit::platform::unix::register_xlib_error_hook,
|
||||
));
|
||||
#[cfg(target_os = "macos")]
|
||||
let preference = glutin::display::DisplayApiPreference::Cgl;
|
||||
#[cfg(target_os = "android")]
|
||||
let preference = glutin::display::DisplayApiPreference::Egl;
|
||||
|
||||
let gl_display = glutin::display::Display::new(raw_display_handle, preference).unwrap();
|
||||
|
||||
let config_template = glutin::config::ConfigTemplateBuilder::new()
|
||||
.prefer_hardware_accelerated(None)
|
||||
.with_depth_size(0)
|
||||
.with_stencil_size(0)
|
||||
.with_transparency(false)
|
||||
.compatible_with_native_window(raw_window_handle)
|
||||
.build();
|
||||
|
||||
let config = gl_display
|
||||
.find_configs(config_template)
|
||||
.unwrap()
|
||||
.next()
|
||||
.unwrap();
|
||||
|
||||
let context_attributes =
|
||||
glutin::context::ContextAttributesBuilder::new().build(Some(raw_window_handle));
|
||||
// for surface creation.
|
||||
let (width, height): (u32, u32) = winit_window.inner_size().into();
|
||||
let surface_attributes =
|
||||
glutin::surface::SurfaceAttributesBuilder::<glutin::surface::WindowSurface>::new()
|
||||
.build(
|
||||
raw_window_handle,
|
||||
std::num::NonZeroU32::new(width).unwrap(),
|
||||
std::num::NonZeroU32::new(height).unwrap(),
|
||||
);
|
||||
// start creating the gl objects
|
||||
let gl_context = gl_display
|
||||
.create_context(&config, &context_attributes)
|
||||
.unwrap();
|
||||
|
||||
let gl_surface = gl_display
|
||||
.create_window_surface(&config, &surface_attributes)
|
||||
.unwrap();
|
||||
|
||||
let gl_context = gl_context.make_current(&gl_surface).unwrap();
|
||||
|
||||
gl_surface
|
||||
.set_swap_interval(
|
||||
&gl_context,
|
||||
glutin::surface::SwapInterval::Wait(std::num::NonZeroU32::new(1).unwrap()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
GlutinWindowContext {
|
||||
window: winit_window,
|
||||
gl_context,
|
||||
gl_display,
|
||||
gl_surface,
|
||||
}
|
||||
}
|
||||
|
||||
fn window(&self) -> &winit::window::Window {
|
||||
&self.window
|
||||
}
|
||||
|
||||
fn resize(&self, physical_size: winit::dpi::PhysicalSize<u32>) {
|
||||
use glutin::surface::GlSurface;
|
||||
self.gl_surface.resize(
|
||||
&self.gl_context,
|
||||
physical_size.width.try_into().unwrap(),
|
||||
physical_size.height.try_into().unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
fn swap_buffers(&self) -> glutin::error::Result<()> {
|
||||
use glutin::surface::GlSurface;
|
||||
self.gl_surface.swap_buffers(&self.gl_context)
|
||||
}
|
||||
|
||||
fn get_proc_address(&self, addr: &std::ffi::CStr) -> *const std::ffi::c_void {
|
||||
use glutin::display::GlDisplay;
|
||||
self.gl_display.get_proc_address(addr)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut clear_color = [0.1, 0.1, 0.1];
|
||||
|
||||
let event_loop = glutin::event_loop::EventLoopBuilder::with_user_event().build();
|
||||
let event_loop = winit::event_loop::EventLoopBuilder::with_user_event().build();
|
||||
let (gl_window, gl) = create_display(&event_loop);
|
||||
let gl = std::sync::Arc::new(gl);
|
||||
|
||||
|
@ -27,16 +141,16 @@ fn main() {
|
|||
});
|
||||
|
||||
*control_flow = if quit {
|
||||
glutin::event_loop::ControlFlow::Exit
|
||||
winit::event_loop::ControlFlow::Exit
|
||||
} else if repaint_after.is_zero() {
|
||||
gl_window.window().request_redraw();
|
||||
glutin::event_loop::ControlFlow::Poll
|
||||
winit::event_loop::ControlFlow::Poll
|
||||
} else if let Some(repaint_after_instant) =
|
||||
std::time::Instant::now().checked_add(repaint_after)
|
||||
{
|
||||
glutin::event_loop::ControlFlow::WaitUntil(repaint_after_instant)
|
||||
winit::event_loop::ControlFlow::WaitUntil(repaint_after_instant)
|
||||
} else {
|
||||
glutin::event_loop::ControlFlow::Wait
|
||||
winit::event_loop::ControlFlow::Wait
|
||||
};
|
||||
|
||||
{
|
||||
|
@ -61,20 +175,19 @@ fn main() {
|
|||
// Platform-dependent event handlers to workaround a winit bug
|
||||
// See: https://github.com/rust-windowing/winit/issues/987
|
||||
// See: https://github.com/rust-windowing/winit/issues/1619
|
||||
glutin::event::Event::RedrawEventsCleared if cfg!(windows) => redraw(),
|
||||
glutin::event::Event::RedrawRequested(_) if !cfg!(windows) => redraw(),
|
||||
winit::event::Event::RedrawEventsCleared if cfg!(windows) => redraw(),
|
||||
winit::event::Event::RedrawRequested(_) if !cfg!(windows) => redraw(),
|
||||
|
||||
glutin::event::Event::WindowEvent { event, .. } => {
|
||||
use glutin::event::WindowEvent;
|
||||
winit::event::Event::WindowEvent { event, .. } => {
|
||||
use winit::event::WindowEvent;
|
||||
if matches!(event, WindowEvent::CloseRequested | WindowEvent::Destroyed) {
|
||||
*control_flow = glutin::event_loop::ControlFlow::Exit;
|
||||
*control_flow = winit::event_loop::ControlFlow::Exit;
|
||||
}
|
||||
|
||||
if let glutin::event::WindowEvent::Resized(physical_size) = &event {
|
||||
if let winit::event::WindowEvent::Resized(physical_size) = &event {
|
||||
gl_window.resize(*physical_size);
|
||||
} else if let glutin::event::WindowEvent::ScaleFactorChanged {
|
||||
new_inner_size,
|
||||
..
|
||||
} else if let winit::event::WindowEvent::ScaleFactorChanged {
|
||||
new_inner_size, ..
|
||||
} = &event
|
||||
{
|
||||
gl_window.resize(**new_inner_size);
|
||||
|
@ -86,10 +199,10 @@ fn main() {
|
|||
gl_window.window().request_redraw();
|
||||
}
|
||||
}
|
||||
glutin::event::Event::LoopDestroyed => {
|
||||
winit::event::Event::LoopDestroyed => {
|
||||
egui_glow.destroy();
|
||||
}
|
||||
glutin::event::Event::NewEvents(glutin::event::StartCause::ResumeTimeReached {
|
||||
winit::event::Event::NewEvents(winit::event::StartCause::ResumeTimeReached {
|
||||
..
|
||||
}) => {
|
||||
gl_window.window().request_redraw();
|
||||
|
@ -101,32 +214,29 @@ fn main() {
|
|||
}
|
||||
|
||||
fn create_display(
|
||||
event_loop: &glutin::event_loop::EventLoop<()>,
|
||||
) -> (
|
||||
glutin::WindowedContext<glutin::PossiblyCurrent>,
|
||||
glow::Context,
|
||||
) {
|
||||
let window_builder = glutin::window::WindowBuilder::new()
|
||||
event_loop: &winit::event_loop::EventLoopWindowTarget<()>,
|
||||
) -> (GlutinWindowContext, glow::Context) {
|
||||
let winit_window = winit::window::WindowBuilder::new()
|
||||
.with_resizable(true)
|
||||
.with_inner_size(glutin::dpi::LogicalSize {
|
||||
.with_inner_size(winit::dpi::LogicalSize {
|
||||
width: 800.0,
|
||||
height: 600.0,
|
||||
})
|
||||
.with_title("egui_glow example")
|
||||
.with_visible(false); // Keep hidden until we've painted something. See https://github.com/emilk/egui/pull/2279
|
||||
.with_visible(false)
|
||||
.build(event_loop)
|
||||
.unwrap(); // Keep hidden until we've painted something. See https://github.com/emilk/egui/pull/2279
|
||||
|
||||
let gl_window = unsafe {
|
||||
glutin::ContextBuilder::new()
|
||||
.with_depth_buffer(0)
|
||||
.with_stencil_buffer(0)
|
||||
.with_vsync(true)
|
||||
.build_windowed(window_builder, event_loop)
|
||||
.unwrap()
|
||||
.make_current()
|
||||
.unwrap()
|
||||
// a lot of the code below has been lifted from glutin example in their repo.
|
||||
let glutin_window_context = unsafe { GlutinWindowContext::new(winit_window) };
|
||||
let gl = unsafe {
|
||||
glow::Context::from_loader_function(|s| {
|
||||
let s = std::ffi::CString::new(s)
|
||||
.expect("failed to construct C string from string for gl proc address");
|
||||
|
||||
glutin_window_context.get_proc_address(&s)
|
||||
})
|
||||
};
|
||||
|
||||
let gl = unsafe { glow::Context::from_loader_function(|s| gl_window.get_proc_address(s)) };
|
||||
|
||||
(gl_window, gl)
|
||||
(glutin_window_context, gl)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue