1
1
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 ;
2
8
use raw_window_handle:: {
3
9
HasRawDisplayHandle , HasRawWindowHandle , RawDisplayHandle , RawWindowHandle ,
4
10
} ;
@@ -10,7 +16,7 @@ use x11::xlib::_XDisplay;
10
16
pub fn create_display < TUserEvent > (
11
17
event_loop : & EventLoop < TUserEvent > ,
12
18
) -> ( GlutinWindowContext , egui_glow:: painter:: Context ) {
13
- let winit_window = WindowBuilder :: new ( )
19
+ let window_builder = WindowBuilder :: new ( )
14
20
. with_visible ( false )
15
21
. with_decorations ( false )
16
22
. with_resizable ( false )
@@ -20,18 +26,49 @@ pub fn create_display<TUserEvent>(
20
26
height : 10 ,
21
27
} )
22
28
. 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
+ } )
25
61
. unwrap ( ) ;
26
62
27
- let gl_window = unsafe { GlutinWindowContext :: new ( winit_window) } ;
63
+ let window = window. unwrap ( ) ;
64
+ let gl_window = unsafe { GlutinWindowContext :: new ( window, gl_config) } ;
28
65
29
66
let gl = unsafe {
30
67
glow:: Context :: from_loader_function ( |s| {
31
68
let s = std:: ffi:: CString :: new ( s)
32
69
. expect ( "failed to construct C string from string for gl proc address" ) ;
33
70
34
- gl_window. get_proc_address ( & s)
71
+ gl_window. gl_display . get_proc_address ( & s)
35
72
} )
36
73
} ;
37
74
@@ -46,53 +83,45 @@ pub struct GlutinWindowContext {
46
83
}
47
84
48
85
impl GlutinWindowContext {
49
- // refactor this function to use `glutin-winit` crate eventually.
50
- // preferably add android support at the same time.
51
86
#[ 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 {
57
88
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
-
75
89
let context_attributes =
76
90
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 ( ) ;
90
91
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 ( ) ) ;
91
120
let gl_surface = gl_display
92
121
. create_window_surface ( & config, & surface_attributes)
93
122
. unwrap ( ) ;
94
123
95
- let gl_context = gl_context . make_current ( & gl_surface) . unwrap ( ) ;
124
+ let gl_context = gl_context_candidate . make_current ( & gl_surface) . unwrap ( ) ;
96
125
97
126
gl_surface
98
127
. set_swap_interval (
@@ -114,7 +143,6 @@ impl GlutinWindowContext {
114
143
}
115
144
116
145
pub fn resize ( & self , physical_size : winit:: dpi:: PhysicalSize < u32 > ) {
117
- use glutin:: surface:: GlSurface ;
118
146
self . gl_surface . resize (
119
147
& self . gl_context ,
120
148
physical_size. width . try_into ( ) . unwrap ( ) ,
@@ -123,15 +151,9 @@ impl GlutinWindowContext {
123
151
}
124
152
125
153
pub fn swap_buffers ( & self ) -> glutin:: error:: Result < ( ) > {
126
- use glutin:: surface:: GlSurface ;
127
154
self . gl_surface . swap_buffers ( & self . gl_context )
128
155
}
129
156
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
-
135
157
pub fn get_focused_monitor ( & self ) -> Option < winit:: monitor:: MonitorHandle > {
136
158
let pointer = self . query_pointer ( ) ;
137
159
let mut monitors = self . window . available_monitors ( ) . filter ( |monitor| {
0 commit comments