11use 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 ;
28use raw_window_handle:: {
39 HasRawDisplayHandle , HasRawWindowHandle , RawDisplayHandle , RawWindowHandle ,
410} ;
@@ -10,7 +16,7 @@ use x11::xlib::_XDisplay;
1016pub 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
4885impl 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