Glutin Upgrade (#2187)
* working. but x11 blurry * fixed x11 blurry. was just accidentally using multisampling even when user didnt request it * allow dbg macro temporarily * add windows WGL fallback support when EGL fails * fmt * glutin features explicitly added * extract glutin context creation into a fn * fix warnings
This commit is contained in:
parent
3ba39c3022
commit
8eb687cf04
3 changed files with 239 additions and 38 deletions
83
Cargo.lock
generated
83
Cargo.lock
generated
|
@ -1261,11 +1261,12 @@ dependencies = [
|
|||
"egui-winit",
|
||||
"egui_glow",
|
||||
"glow",
|
||||
"glutin",
|
||||
"glutin 0.30.0",
|
||||
"image",
|
||||
"js-sys",
|
||||
"percent-encoding",
|
||||
"puffin",
|
||||
"raw-window-handle 0.5.0",
|
||||
"ron",
|
||||
"serde",
|
||||
"tracing",
|
||||
|
@ -1399,7 +1400,7 @@ dependencies = [
|
|||
"egui",
|
||||
"egui-winit",
|
||||
"glow",
|
||||
"glutin",
|
||||
"glutin 0.29.1",
|
||||
"memoffset",
|
||||
"puffin",
|
||||
"tracing",
|
||||
|
@ -1863,7 +1864,7 @@ dependencies = [
|
|||
"backtrace",
|
||||
"fnv",
|
||||
"gl_generator",
|
||||
"glutin",
|
||||
"glutin 0.29.1",
|
||||
"lazy_static",
|
||||
"memoffset",
|
||||
"smallvec",
|
||||
|
@ -1897,10 +1898,10 @@ dependencies = [
|
|||
"cgl",
|
||||
"cocoa",
|
||||
"core-foundation",
|
||||
"glutin_egl_sys",
|
||||
"glutin_egl_sys 0.1.6",
|
||||
"glutin_gles2_sys",
|
||||
"glutin_glx_sys",
|
||||
"glutin_wgl_sys",
|
||||
"glutin_glx_sys 0.1.8",
|
||||
"glutin_wgl_sys 0.1.5",
|
||||
"libloading",
|
||||
"log",
|
||||
"objc",
|
||||
|
@ -1914,6 +1915,29 @@ dependencies = [
|
|||
"winit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glutin"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34acbf502536f1d125f0fc09b6ad8824e93e6da7b99e86d3383e6b8310ba3554"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg_aliases",
|
||||
"cgl",
|
||||
"cocoa",
|
||||
"core-foundation",
|
||||
"glutin_egl_sys 0.3.0",
|
||||
"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",
|
||||
"windows-sys",
|
||||
"x11-dl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glutin_egl_sys"
|
||||
version = "0.1.6"
|
||||
|
@ -1924,6 +1948,16 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glutin_egl_sys"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c3c95a2d7a54bab0c74759794efb5cd63470d4504cbe85ed4114dc82c98bdc1"
|
||||
dependencies = [
|
||||
"gl_generator",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glutin_gles2_sys"
|
||||
version = "0.1.5"
|
||||
|
@ -1944,6 +1978,16 @@ dependencies = [
|
|||
"x11-dl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glutin_glx_sys"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "947c4850c58211c9627969c2b4e2674764b81ae5b47bab2c9a477d7942f96e0f"
|
||||
dependencies = [
|
||||
"gl_generator",
|
||||
"x11-dl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glutin_wgl_sys"
|
||||
version = "0.1.5"
|
||||
|
@ -1953,6 +1997,15 @@ dependencies = [
|
|||
"gl_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glutin_wgl_sys"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20c33975a6c9d49d72c8f032a60079bf8df536954fbf9e4cee90396ace815c57"
|
||||
dependencies = [
|
||||
"gl_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gobject-sys"
|
||||
version = "0.15.10"
|
||||
|
@ -4246,7 +4299,7 @@ dependencies = [
|
|||
"scoped-tls",
|
||||
"wayland-commons",
|
||||
"wayland-scanner",
|
||||
"wayland-sys",
|
||||
"wayland-sys 0.29.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4258,7 +4311,7 @@ dependencies = [
|
|||
"nix 0.22.3",
|
||||
"once_cell",
|
||||
"smallvec",
|
||||
"wayland-sys",
|
||||
"wayland-sys 0.29.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4279,7 +4332,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "83281d69ee162b59031c666385e93bde4039ec553b90c4191cdb128ceea29a3a"
|
||||
dependencies = [
|
||||
"wayland-client",
|
||||
"wayland-sys",
|
||||
"wayland-sys 0.29.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4316,6 +4369,18 @@ dependencies = [
|
|||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-sys"
|
||||
version = "0.30.0-beta.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1117fe4570fe063122ba2b1b1e39e56fb1a73921d395f9288af06af0dd1c7f55"
|
||||
dependencies = [
|
||||
"dlib",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.60"
|
||||
|
|
|
@ -87,7 +87,16 @@ egui-winit = { version = "0.19.0", path = "../egui-winit", default-features = fa
|
|||
"clipboard",
|
||||
"links",
|
||||
] }
|
||||
glutin = { version = "0.29.0" }
|
||||
# we can expose these to user so that they can select which backends they want to enable to avoid compiling useless deps.
|
||||
# this can be done at the same time we expose x11/wayland features of winit crate.
|
||||
glutin = { version = "0.30.0", features = [
|
||||
"egl",
|
||||
"glx",
|
||||
"x11",
|
||||
"wayland",
|
||||
"wgl",
|
||||
] }
|
||||
raw-window-handle = { version = "0.5.0" }
|
||||
winit = "0.27.2"
|
||||
|
||||
# optional native:
|
||||
|
@ -95,7 +104,7 @@ dark-light = { version = "0.2.1", optional = true }
|
|||
directories-next = { version = "2", optional = true }
|
||||
egui-wgpu = { version = "0.19.0", path = "../egui-wgpu", optional = true, features = [
|
||||
"winit",
|
||||
] }
|
||||
] } # if wgpu is used, use it with winit
|
||||
image = { version = "0.24", optional = true, default-features = false, features = [
|
||||
"png",
|
||||
] }
|
||||
|
|
|
@ -305,7 +305,145 @@ mod glow_integration {
|
|||
|
||||
// Conceptually this will be split out eventually so that the rest of the state
|
||||
// can be persistent.
|
||||
gl_window: glutin::WindowedContext<glutin::PossiblyCurrent>,
|
||||
gl_window: GlutinWindowContext,
|
||||
}
|
||||
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,
|
||||
native_options: &epi::NativeOptions,
|
||||
) -> Self {
|
||||
use glutin::prelude::*;
|
||||
use raw_window_handle::*;
|
||||
let hardware_acceleration = match native_options.hardware_acceleration {
|
||||
crate::HardwareAcceleration::Required => Some(true),
|
||||
crate::HardwareAcceleration::Preferred => None,
|
||||
crate::HardwareAcceleration::Off => Some(false),
|
||||
};
|
||||
|
||||
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.
|
||||
// TODO: check whether we can expose these options as "features", so that users can select the relevant backend they want.
|
||||
|
||||
// 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)
|
||||
.expect("failed to create glutin display");
|
||||
let swap_interval = if native_options.vsync {
|
||||
glutin::surface::SwapInterval::Wait(std::num::NonZeroU32::new(1).unwrap())
|
||||
} else {
|
||||
glutin::surface::SwapInterval::DontWait
|
||||
};
|
||||
|
||||
let config_template = glutin::config::ConfigTemplateBuilder::new()
|
||||
.prefer_hardware_accelerated(hardware_acceleration)
|
||||
.with_depth_size(native_options.depth_buffer);
|
||||
// we don't know if multi sampling option is set. so, check if its more than 0.
|
||||
let config_template = if native_options.multisampling > 0 {
|
||||
config_template.with_multisampling(
|
||||
native_options
|
||||
.multisampling
|
||||
.try_into()
|
||||
.expect("failed to fit multisamples into u8"),
|
||||
)
|
||||
} else {
|
||||
config_template
|
||||
};
|
||||
let config_template = config_template
|
||||
.with_stencil_size(native_options.stencil_buffer)
|
||||
.with_transparency(native_options.transparent)
|
||||
.compatible_with_native_window(raw_window_handle)
|
||||
.build();
|
||||
// finds all valid configurations supported by this display that match the config_template
|
||||
// this is where we will try to get a "fallback" config if we are okay with ignoring some native
|
||||
// options required by user like multi sampling, srgb, transparency etc..
|
||||
// TODO: need to figure out a good fallback config template
|
||||
let config = gl_display
|
||||
.find_configs(config_template)
|
||||
.expect("failed to find even a single matching configuration")
|
||||
.next()
|
||||
.expect("failed to find a matching configuration for creating opengl context");
|
||||
|
||||
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)
|
||||
.expect("failed to create opengl context");
|
||||
|
||||
let gl_surface = gl_display
|
||||
.create_window_surface(&config, &surface_attributes)
|
||||
.expect("failed to create glutin window surface");
|
||||
let gl_context = gl_context
|
||||
.make_current(&gl_surface)
|
||||
.expect("failed to make gl context current");
|
||||
gl_surface
|
||||
.set_swap_interval(&gl_context, swap_interval)
|
||||
.expect("failed to set vsync swap interval");
|
||||
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()
|
||||
.expect("physical size must not be zero"),
|
||||
physical_size
|
||||
.height
|
||||
.try_into()
|
||||
.expect("physical size must not be zero"),
|
||||
);
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
struct GlowWinitApp {
|
||||
|
@ -347,44 +485,33 @@ mod glow_integration {
|
|||
storage: Option<&dyn epi::Storage>,
|
||||
title: &String,
|
||||
native_options: &NativeOptions,
|
||||
) -> (
|
||||
glutin::WindowedContext<glutin::PossiblyCurrent>,
|
||||
glow::Context,
|
||||
) {
|
||||
) -> (GlutinWindowContext, glow::Context) {
|
||||
crate::profile_function!();
|
||||
|
||||
use crate::HardwareAcceleration;
|
||||
|
||||
let hardware_acceleration = match native_options.hardware_acceleration {
|
||||
HardwareAcceleration::Required => Some(true),
|
||||
HardwareAcceleration::Preferred => None,
|
||||
HardwareAcceleration::Off => Some(false),
|
||||
};
|
||||
let window_settings = epi_integration::load_window_settings(storage);
|
||||
|
||||
let window_builder = epi_integration::window_builder(native_options, &window_settings)
|
||||
.with_title(title)
|
||||
.with_transparent(native_options.transparent)
|
||||
// Keep hidden until we've painted something. See https://github.com/emilk/egui/pull/2279
|
||||
// We must also keep the window hidden until AccessKit is initialized.
|
||||
.with_visible(false);
|
||||
let winit_window = window_builder
|
||||
.build(event_loop)
|
||||
.expect("failed to create winit window");
|
||||
// a lot of the code below has been lifted from glutin example in their repo.
|
||||
let glutin_window_context =
|
||||
unsafe { GlutinWindowContext::new(winit_window, native_options) };
|
||||
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");
|
||||
|
||||
let gl_window = unsafe {
|
||||
glutin::ContextBuilder::new()
|
||||
.with_hardware_acceleration(hardware_acceleration)
|
||||
.with_depth_buffer(native_options.depth_buffer)
|
||||
.with_multisampling(native_options.multisampling)
|
||||
.with_stencil_buffer(native_options.stencil_buffer)
|
||||
.with_vsync(native_options.vsync)
|
||||
.build_windowed(window_builder, event_loop)
|
||||
.unwrap()
|
||||
.make_current()
|
||||
.unwrap()
|
||||
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)
|
||||
}
|
||||
|
||||
fn init_run_state(&mut self, event_loop: &EventLoopWindowTarget<UserEvent>) {
|
||||
|
|
Loading…
Reference in a new issue