Skip to content

Commit 81a84ce

Browse files
committed
Fix GL config bug
1 parent 69ee6f2 commit 81a84ce

File tree

1 file changed

+72
-50
lines changed
  • src/vonal_daemon/windowing

1 file changed

+72
-50
lines changed

src/vonal_daemon/windowing/mod.rs

+72-50
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
use egui_glow::glow;
2+
use glutin::config::ConfigTemplateBuilder;
3+
use glutin::context::{ContextApi, ContextAttributesBuilder, Version};
4+
use glutin::display::GetGlDisplay;
5+
use glutin::prelude::*;
6+
use glutin::surface::GlSurface;
7+
use glutin_winit::GlWindow;
28
use raw_window_handle::{
39
HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle,
410
};
@@ -10,7 +16,7 @@ use x11::xlib::_XDisplay;
1016
pub fn create_display<TUserEvent>(
1117
event_loop: &EventLoop<TUserEvent>,
1218
) -> (GlutinWindowContext, egui_glow::painter::Context) {
13-
let winit_window = WindowBuilder::new()
19+
let window_builder = WindowBuilder::new()
1420
.with_visible(false)
1521
.with_decorations(false)
1622
.with_resizable(false)
@@ -20,18 +26,49 @@ pub fn create_display<TUserEvent>(
2026
height: 10,
2127
})
2228
.with_transparent(true)
23-
.with_title("Vonal")
24-
.build(event_loop)
29+
.with_title("Vonal");
30+
31+
let template_builder = ConfigTemplateBuilder::new().with_alpha_size(8);
32+
33+
let (window, gl_config) = glutin_winit::DisplayBuilder::new()
34+
.with_window_builder(Some(window_builder.clone()))
35+
.build(event_loop, template_builder, |configs| {
36+
// Find the config with the maximum number of samples
37+
configs
38+
.reduce(|acc, current| {
39+
let is_current_transparent = current.supports_transparency().unwrap_or(false);
40+
let is_acc_transparent = acc.supports_transparency().unwrap_or(false);
41+
let gain_bigger_samples = current.num_samples() > acc.num_samples();
42+
43+
let case_transparency_is_not_supported =
44+
!is_acc_transparent && !is_current_transparent && gain_bigger_samples;
45+
let case_transparency_is_supported =
46+
is_acc_transparent && is_current_transparent && gain_bigger_samples;
47+
let case_transparency_become_supported =
48+
!is_acc_transparent && is_current_transparent;
49+
let is_current_better = case_transparency_become_supported
50+
|| case_transparency_is_supported
51+
|| case_transparency_is_not_supported;
52+
53+
if is_current_better {
54+
current
55+
} else {
56+
acc
57+
}
58+
})
59+
.unwrap()
60+
})
2561
.unwrap();
2662

27-
let gl_window = unsafe { GlutinWindowContext::new(winit_window) };
63+
let window = window.unwrap();
64+
let gl_window = unsafe { GlutinWindowContext::new(window, gl_config) };
2865

2966
let gl = unsafe {
3067
glow::Context::from_loader_function(|s| {
3168
let s = std::ffi::CString::new(s)
3269
.expect("failed to construct C string from string for gl proc address");
3370

34-
gl_window.get_proc_address(&s)
71+
gl_window.gl_display.get_proc_address(&s)
3572
})
3673
};
3774

@@ -46,53 +83,45 @@ pub struct GlutinWindowContext {
4683
}
4784

4885
impl GlutinWindowContext {
49-
// refactor this function to use `glutin-winit` crate eventually.
50-
// preferably add android support at the same time.
5186
#[allow(unsafe_code)]
52-
unsafe fn new(winit_window: winit::window::Window) -> Self {
53-
use glutin::prelude::*;
54-
use raw_window_handle::*;
55-
56-
let raw_display_handle = winit_window.raw_display_handle();
87+
unsafe fn new(winit_window: winit::window::Window, config: glutin::config::Config) -> Self {
5788
let raw_window_handle = winit_window.raw_window_handle();
58-
59-
// This was GlxThenEgl, but it broke
60-
#[cfg(target_os = "linux")]
61-
let preference = glutin::display::DisplayApiPreference::Egl;
62-
63-
let gl_display = glutin::display::Display::new(raw_display_handle, preference).unwrap();
64-
65-
let config_template = glutin::config::ConfigTemplateBuilder::new()
66-
.compatible_with_native_window(raw_window_handle)
67-
.build();
68-
69-
let config = gl_display
70-
.find_configs(config_template)
71-
.unwrap()
72-
.next()
73-
.unwrap();
74-
7589
let context_attributes =
7690
glutin::context::ContextAttributesBuilder::new().build(Some(raw_window_handle));
77-
// for surface creation.
78-
let (width, height): (u32, u32) = winit_window.inner_size().into();
79-
let surface_attributes =
80-
glutin::surface::SurfaceAttributesBuilder::<glutin::surface::WindowSurface>::new()
81-
.build(
82-
raw_window_handle,
83-
std::num::NonZeroU32::new(width).unwrap(),
84-
std::num::NonZeroU32::new(height).unwrap(),
85-
);
86-
// start creating the gl objects
87-
let gl_context = gl_display
88-
.create_context(&config, &context_attributes)
89-
.unwrap();
9091

92+
// Since glutin by default tries to create OpenGL core context, which may not be
93+
// present we should try gles.
94+
let fallback_context_attributes = ContextAttributesBuilder::new()
95+
.with_context_api(ContextApi::Gles(None))
96+
.build(Some(raw_window_handle));
97+
98+
// There are also some old devices that support neither modern OpenGL nor GLES.
99+
// To support these we can try and create a 2.1 context.
100+
let legacy_context_attributes = ContextAttributesBuilder::new()
101+
.with_context_api(ContextApi::OpenGl(Some(Version::new(2, 1))))
102+
.build(Some(raw_window_handle));
103+
104+
let gl_display = config.display();
105+
let gl_context_candidate = unsafe {
106+
gl_display
107+
.create_context(&config, &context_attributes)
108+
.unwrap_or_else(|_| {
109+
gl_display
110+
.create_context(&config, &fallback_context_attributes)
111+
.unwrap_or_else(|_| {
112+
gl_display
113+
.create_context(&config, &legacy_context_attributes)
114+
.expect("failed to create context")
115+
})
116+
})
117+
};
118+
119+
let surface_attributes = winit_window.build_surface_attributes(Default::default());
91120
let gl_surface = gl_display
92121
.create_window_surface(&config, &surface_attributes)
93122
.unwrap();
94123

95-
let gl_context = gl_context.make_current(&gl_surface).unwrap();
124+
let gl_context = gl_context_candidate.make_current(&gl_surface).unwrap();
96125

97126
gl_surface
98127
.set_swap_interval(
@@ -114,7 +143,6 @@ impl GlutinWindowContext {
114143
}
115144

116145
pub fn resize(&self, physical_size: winit::dpi::PhysicalSize<u32>) {
117-
use glutin::surface::GlSurface;
118146
self.gl_surface.resize(
119147
&self.gl_context,
120148
physical_size.width.try_into().unwrap(),
@@ -123,15 +151,9 @@ impl GlutinWindowContext {
123151
}
124152

125153
pub fn swap_buffers(&self) -> glutin::error::Result<()> {
126-
use glutin::surface::GlSurface;
127154
self.gl_surface.swap_buffers(&self.gl_context)
128155
}
129156

130-
fn get_proc_address(&self, addr: &std::ffi::CStr) -> *const std::ffi::c_void {
131-
use glutin::display::GlDisplay;
132-
self.gl_display.get_proc_address(addr)
133-
}
134-
135157
pub fn get_focused_monitor(&self) -> Option<winit::monitor::MonitorHandle> {
136158
let pointer = self.query_pointer();
137159
let mut monitors = self.window.available_monitors().filter(|monitor| {

0 commit comments

Comments
 (0)