1 use crate::api::egl::{ 2 Context as EglContext, NativeDisplay, SurfaceType as EglSurfaceType, 3 }; 4 use crate::{ 5 ContextError, CreationError, GlAttributes, PixelFormat, 6 PixelFormatRequirements, Rect, 7 }; 8 9 use crate::platform::unix::{EventLoopWindowTargetExtUnix, WindowExtUnix}; 10 use glutin_egl_sys as ffi; 11 use wayland_client::egl as wegl; 12 pub use wayland_client::sys::client::wl_display; 13 use winit; 14 use winit::dpi; 15 use winit::event_loop::EventLoopWindowTarget; 16 use winit::window::{Window, WindowBuilder}; 17 18 use std::ops::Deref; 19 use std::os::raw; 20 use std::sync::Arc; 21 22 pub struct EglSurface(Arc<wegl::WlEglSurface>); 23 24 impl std::fmt::Debug for EglSurface { fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result25 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 26 write!(f, "EglSurface(...)") 27 } 28 } 29 30 #[derive(Debug)] 31 pub enum Context { 32 Windowed(EglContext, EglSurface), 33 PBuffer(EglContext), 34 Surfaceless(EglContext), 35 } 36 37 impl Deref for Context { 38 type Target = EglContext; 39 deref(&self) -> &Self::Target40 fn deref(&self) -> &Self::Target { 41 match self { 42 Context::Windowed(ctx, _) => ctx, 43 Context::PBuffer(ctx) => ctx, 44 Context::Surfaceless(ctx) => ctx, 45 } 46 } 47 } 48 49 impl Context { 50 #[inline] new_headless<T>( el: &EventLoopWindowTarget<T>, pf_reqs: &PixelFormatRequirements, gl_attr: &GlAttributes<&Context>, size: Option<dpi::PhysicalSize<u32>>, ) -> Result<Self, CreationError>51 pub fn new_headless<T>( 52 el: &EventLoopWindowTarget<T>, 53 pf_reqs: &PixelFormatRequirements, 54 gl_attr: &GlAttributes<&Context>, 55 size: Option<dpi::PhysicalSize<u32>>, 56 ) -> Result<Self, CreationError> { 57 let gl_attr = gl_attr.clone().map_sharing(|c| &**c); 58 let display_ptr = el.wayland_display().unwrap() as *const _; 59 let native_display = 60 NativeDisplay::Wayland(Some(display_ptr as *const _)); 61 if let Some(size) = size { 62 let context = EglContext::new( 63 pf_reqs, 64 &gl_attr, 65 native_display, 66 EglSurfaceType::PBuffer, 67 |c, _| Ok(c[0]), 68 ) 69 .and_then(|p| p.finish_pbuffer(size))?; 70 let context = Context::PBuffer(context); 71 Ok(context) 72 } else { 73 // Surfaceless 74 let context = EglContext::new( 75 pf_reqs, 76 &gl_attr, 77 native_display, 78 EglSurfaceType::Surfaceless, 79 |c, _| Ok(c[0]), 80 ) 81 .and_then(|p| p.finish_surfaceless())?; 82 let context = Context::Surfaceless(context); 83 Ok(context) 84 } 85 } 86 87 #[inline] new<T>( wb: WindowBuilder, el: &EventLoopWindowTarget<T>, pf_reqs: &PixelFormatRequirements, gl_attr: &GlAttributes<&Context>, ) -> Result<(Window, Self), CreationError>88 pub fn new<T>( 89 wb: WindowBuilder, 90 el: &EventLoopWindowTarget<T>, 91 pf_reqs: &PixelFormatRequirements, 92 gl_attr: &GlAttributes<&Context>, 93 ) -> Result<(Window, Self), CreationError> { 94 let win = wb.build(el)?; 95 96 let size = win.inner_size(); 97 let (width, height): (u32, u32) = size.into(); 98 99 let display_ptr = win.wayland_display().unwrap() as *const _; 100 let surface = win.wayland_surface(); 101 let surface = match surface { 102 Some(s) => s, 103 None => { 104 return Err(CreationError::NotSupported( 105 "Wayland not found".to_string(), 106 )); 107 } 108 }; 109 110 let context = Self::new_raw_context( 111 display_ptr, 112 surface, 113 width, 114 height, 115 pf_reqs, 116 gl_attr, 117 )?; 118 Ok((win, context)) 119 } 120 121 #[inline] new_raw_context( display_ptr: *const wl_display, surface: *mut raw::c_void, width: u32, height: u32, pf_reqs: &PixelFormatRequirements, gl_attr: &GlAttributes<&Context>, ) -> Result<Self, CreationError>122 pub fn new_raw_context( 123 display_ptr: *const wl_display, 124 surface: *mut raw::c_void, 125 width: u32, 126 height: u32, 127 pf_reqs: &PixelFormatRequirements, 128 gl_attr: &GlAttributes<&Context>, 129 ) -> Result<Self, CreationError> { 130 let egl_surface = unsafe { 131 wegl::WlEglSurface::new_from_raw( 132 surface as *mut _, 133 width as i32, 134 height as i32, 135 ) 136 }; 137 let context = { 138 let gl_attr = gl_attr.clone().map_sharing(|c| &**c); 139 let native_display = 140 NativeDisplay::Wayland(Some(display_ptr as *const _)); 141 EglContext::new( 142 pf_reqs, 143 &gl_attr, 144 native_display, 145 EglSurfaceType::Window, 146 |c, _| Ok(c[0]), 147 ) 148 .and_then(|p| p.finish(egl_surface.ptr() as *const _))? 149 }; 150 let context = 151 Context::Windowed(context, EglSurface(Arc::new(egl_surface))); 152 Ok(context) 153 } 154 155 #[inline] make_current(&self) -> Result<(), ContextError>156 pub unsafe fn make_current(&self) -> Result<(), ContextError> { 157 (**self).make_current() 158 } 159 160 #[inline] make_not_current(&self) -> Result<(), ContextError>161 pub unsafe fn make_not_current(&self) -> Result<(), ContextError> { 162 (**self).make_not_current() 163 } 164 165 #[inline] is_current(&self) -> bool166 pub fn is_current(&self) -> bool { 167 (**self).is_current() 168 } 169 170 #[inline] get_api(&self) -> crate::Api171 pub fn get_api(&self) -> crate::Api { 172 (**self).get_api() 173 } 174 175 #[inline] raw_handle(&self) -> ffi::EGLContext176 pub unsafe fn raw_handle(&self) -> ffi::EGLContext { 177 (**self).raw_handle() 178 } 179 180 #[inline] get_egl_display(&self) -> Option<*const raw::c_void>181 pub unsafe fn get_egl_display(&self) -> Option<*const raw::c_void> { 182 Some((**self).get_egl_display()) 183 } 184 185 #[inline] resize(&self, width: u32, height: u32)186 pub fn resize(&self, width: u32, height: u32) { 187 match self { 188 Context::Windowed(_, surface) => { 189 surface.0.resize(width as i32, height as i32, 0, 0) 190 } 191 _ => unreachable!(), 192 } 193 } 194 195 #[inline] get_proc_address(&self, addr: &str) -> *const core::ffi::c_void196 pub fn get_proc_address(&self, addr: &str) -> *const core::ffi::c_void { 197 (**self).get_proc_address(addr) 198 } 199 200 #[inline] swap_buffers(&self) -> Result<(), ContextError>201 pub fn swap_buffers(&self) -> Result<(), ContextError> { 202 (**self).swap_buffers() 203 } 204 205 #[inline] swap_buffers_with_damage( &self, rects: &[Rect], ) -> Result<(), ContextError>206 pub fn swap_buffers_with_damage( 207 &self, 208 rects: &[Rect], 209 ) -> Result<(), ContextError> { 210 (**self).swap_buffers_with_damage(rects) 211 } 212 213 #[inline] swap_buffers_with_damage_supported(&self) -> bool214 pub fn swap_buffers_with_damage_supported(&self) -> bool { 215 (**self).swap_buffers_with_damage_supported() 216 } 217 218 #[inline] get_pixel_format(&self) -> PixelFormat219 pub fn get_pixel_format(&self) -> PixelFormat { 220 (**self).get_pixel_format().clone() 221 } 222 } 223