Added logging to egl&winit + small bugfixes

- Added logging to winit & egl
- Fixed winit pointer scroll event only yielding horizontal events
- Fixed unsupported double_buffering for egl
This commit is contained in:
Drakulix 2017-06-04 23:11:26 +02:00
parent 4053d2bc30
commit 2453545329
2 changed files with 162 additions and 34 deletions

View File

@ -126,8 +126,14 @@ impl EGLContext {
/// ///
/// This method is marked unsafe, because the contents of `Native` cannot be verified and msy /// This method is marked unsafe, because the contents of `Native` cannot be verified and msy
/// contain dangeling pointers are similar unsafe content /// contain dangeling pointers are similar unsafe content
pub unsafe fn new(native: Native, mut attributes: GlAttributes, reqs: PixelFormatRequirements) pub unsafe fn new<L>(native: Native, mut attributes: GlAttributes, reqs: PixelFormatRequirements, logger: L)
-> Result<EGLContext, CreationError> { -> Result<EGLContext, CreationError>
where L: Into<Option<::slog::Logger>>
{
let logger = logger.into();
let log = ::slog_or_stdlog(logger.clone()).new(o!("smithay_module" => "renderer_egl"));
trace!(log, "Loading libEGL");
let lib = Library::new("libEGL.so.1")?; let lib = Library::new("libEGL.so.1")?;
let egl = ffi::egl::Egl::load_with(|sym| { let egl = ffi::egl::Egl::load_with(|sym| {
let name = CString::new(sym).unwrap(); let name = CString::new(sym).unwrap();
@ -138,29 +144,32 @@ impl EGLContext {
} }
}); });
// If no version is given, try OpenGLES 3.0, if available, // If no version is given, try OpenGLES 3.0, if available,
// fallback to 2.0 otherwise // fallback to 2.0 otherwise
let version = match attributes.version { let version = match attributes.version {
Some((3, x)) => (3, x), Some((3, x)) => (3, x),
Some((2, x)) => (2, x), Some((2, x)) => (2, x),
None => { None => {
debug!(log, "Trying to initialize EGL with OpenGLES 3.0");
attributes.version = Some((3, 0)); attributes.version = Some((3, 0));
match EGLContext::new(native, attributes, reqs) { match EGLContext::new(native, attributes, reqs, logger.clone()) {
Ok(x) => return Ok(x), Ok(x) => return Ok(x),
Err(_) => { Err(err) => {
// TODO log warn!(log, "EGL OpenGLES 3.0 Initialization failed with {}", err);
debug!(log, "Trying to initialize EGL with OpenGLES 2.0");
attributes.version = Some((2, 0)); attributes.version = Some((2, 0));
return EGLContext::new(native, attributes, reqs); return EGLContext::new(native, attributes, reqs, logger);
} }
} }
} }
Some((1, _)) => { Some((1, _)) => {
// TODO logging + error, 1.0 not supported error!(log, "OpenGLES 1.* is not supported by the EGL renderer backend");
unimplemented!() return Err(CreationError::OpenGlVersionNotSupported)
} }
Some(_) => { Some(version) => {
// TODO logging + error, version not supported error!(log, "OpenGLES {:?} is unknown and not supported by the EGL renderer backend", version);
unimplemented!() return Err(CreationError::OpenGlVersionNotSupported)
} }
}; };
@ -179,31 +188,38 @@ impl EGLContext {
} }
}; };
debug!(log, "EGL No-Display Extensions: {:?}", dp_extensions);
let has_dp_extension = |e: &str| dp_extensions.iter().any(|s| s == e); let has_dp_extension = |e: &str| dp_extensions.iter().any(|s| s == e);
let display = match native { let display = match native {
Native::X11(display, _) if has_dp_extension("EGL_KHR_platform_x11") && Native::X11(display, _) if has_dp_extension("EGL_KHR_platform_x11") &&
egl.GetPlatformDisplay.is_loaded() => { egl.GetPlatformDisplay.is_loaded() => {
trace!(log, "EGL Display Initialization via EGL_KHR_platform_x11");
egl.GetPlatformDisplay(ffi::egl::PLATFORM_X11_KHR, display as *mut _, ptr::null()) egl.GetPlatformDisplay(ffi::egl::PLATFORM_X11_KHR, display as *mut _, ptr::null())
} }
Native::X11(display, _) if has_dp_extension("EGL_EXT_platform_x11") && Native::X11(display, _) if has_dp_extension("EGL_EXT_platform_x11") &&
egl.GetPlatformDisplayEXT.is_loaded() => { egl.GetPlatformDisplayEXT.is_loaded() => {
trace!(log, "EGL Display Initialization via EGL_EXT_platform_x11");
egl.GetPlatformDisplayEXT(ffi::egl::PLATFORM_X11_EXT, display as *mut _, ptr::null()) egl.GetPlatformDisplayEXT(ffi::egl::PLATFORM_X11_EXT, display as *mut _, ptr::null())
} }
Native::Gbm(display, _) if has_dp_extension("EGL_KHR_platform_gbm") && Native::Gbm(display, _) if has_dp_extension("EGL_KHR_platform_gbm") &&
egl.GetPlatformDisplay.is_loaded() => { egl.GetPlatformDisplay.is_loaded() => {
trace!(log, "EGL Display Initialization via EGL_KHR_platform_gbm");
egl.GetPlatformDisplay(ffi::egl::PLATFORM_GBM_KHR, display as *mut _, ptr::null()) egl.GetPlatformDisplay(ffi::egl::PLATFORM_GBM_KHR, display as *mut _, ptr::null())
} }
Native::Gbm(display, _) if has_dp_extension("EGL_MESA_platform_gbm") && Native::Gbm(display, _) if has_dp_extension("EGL_MESA_platform_gbm") &&
egl.GetPlatformDisplayEXT.is_loaded() => { egl.GetPlatformDisplayEXT.is_loaded() => {
trace!(log, "EGL Display Initialization via EGL_MESA_platform_gbm");
egl.GetPlatformDisplayEXT(ffi::egl::PLATFORM_GBM_KHR, display as *mut _, ptr::null()) egl.GetPlatformDisplayEXT(ffi::egl::PLATFORM_GBM_KHR, display as *mut _, ptr::null())
} }
Native::Wayland(display, _) if has_dp_extension("EGL_KHR_platform_wayland") && Native::Wayland(display, _) if has_dp_extension("EGL_KHR_platform_wayland") &&
egl.GetPlatformDisplay.is_loaded() => { egl.GetPlatformDisplay.is_loaded() => {
trace!(log, "EGL Display Initialization via EGL_KHR_platform_wayland");
egl.GetPlatformDisplay(ffi::egl::PLATFORM_WAYLAND_KHR, egl.GetPlatformDisplay(ffi::egl::PLATFORM_WAYLAND_KHR,
display as *mut _, display as *mut _,
ptr::null()) ptr::null())
@ -211,6 +227,7 @@ impl EGLContext {
Native::Wayland(display, _) if has_dp_extension("EGL_EXT_platform_wayland") && Native::Wayland(display, _) if has_dp_extension("EGL_EXT_platform_wayland") &&
egl.GetPlatformDisplayEXT.is_loaded() => { egl.GetPlatformDisplayEXT.is_loaded() => {
trace!(log, "EGL Display Initialization via EGL_EXT_platform_wayland");
egl.GetPlatformDisplayEXT(ffi::egl::PLATFORM_WAYLAND_EXT, egl.GetPlatformDisplayEXT(ffi::egl::PLATFORM_WAYLAND_EXT,
display as *mut _, display as *mut _,
ptr::null()) ptr::null())
@ -218,7 +235,10 @@ impl EGLContext {
Native::X11(display, _) | Native::X11(display, _) |
Native::Gbm(display, _) | Native::Gbm(display, _) |
Native::Wayland(display, _) => egl.GetDisplay(display as *mut _), Native::Wayland(display, _) => {
trace!(log, "Default EGL Display Initialization via GetDisplay");
egl.GetDisplay(display as *mut _)
},
}; };
let egl_version = { let egl_version = {
@ -229,6 +249,9 @@ impl EGLContext {
return Err(CreationError::OsError(String::from("eglInitialize failed"))); return Err(CreationError::OsError(String::from("eglInitialize failed")));
} }
info!(log, "EGL Initialized");
info!(log, "EGL Version: {:?}", (major, minor));
(major, minor) (major, minor)
}; };
@ -243,7 +266,10 @@ impl EGLContext {
vec![] vec![]
}; };
info!(log, "EGL Extensions: {:?}", extensions);
if egl_version >= (1, 2) && egl.BindAPI(ffi::egl::OPENGL_ES_API) == 0 { if egl_version >= (1, 2) && egl.BindAPI(ffi::egl::OPENGL_ES_API) == 0 {
error!(log, "OpenGLES not supported by the underlying EGL implementation");
return Err(CreationError::OpenGlVersionNotSupported); return Err(CreationError::OpenGlVersionNotSupported);
} }
@ -251,10 +277,13 @@ impl EGLContext {
let mut out: Vec<c_int> = Vec::with_capacity(37); let mut out: Vec<c_int> = Vec::with_capacity(37);
if egl_version >= (1, 2) { if egl_version >= (1, 2) {
trace!(log, "Setting COLOR_BUFFER_TYPE to RGB_BUFFER");
out.push(ffi::egl::COLOR_BUFFER_TYPE as c_int); out.push(ffi::egl::COLOR_BUFFER_TYPE as c_int);
out.push(ffi::egl::RGB_BUFFER as c_int); out.push(ffi::egl::RGB_BUFFER as c_int);
} }
trace!(log, "Setting SURFACE_TYPE to WINDOW");
out.push(ffi::egl::SURFACE_TYPE as c_int); out.push(ffi::egl::SURFACE_TYPE as c_int);
// TODO: Some versions of Mesa report a BAD_ATTRIBUTE error // TODO: Some versions of Mesa report a BAD_ATTRIBUTE error
// if we ask for PBUFFER_BIT as well as WINDOW_BIT // if we ask for PBUFFER_BIT as well as WINDOW_BIT
@ -263,19 +292,25 @@ impl EGLContext {
match version { match version {
(3, _) => { (3, _) => {
if egl_version < (1, 3) { if egl_version < (1, 3) {
error!(log, "OpenglES 3.* is not supported on EGL Versions lower then 1.3");
return Err(CreationError::NoAvailablePixelFormat); return Err(CreationError::NoAvailablePixelFormat);
} }
trace!(log, "Setting RENDERABLE_TYPE to OPENGL_ES3");
out.push(ffi::egl::RENDERABLE_TYPE as c_int); out.push(ffi::egl::RENDERABLE_TYPE as c_int);
out.push(ffi::egl::OPENGL_ES3_BIT as c_int); out.push(ffi::egl::OPENGL_ES3_BIT as c_int);
trace!(log, "Setting CONFORMANT to OPENGL_ES3");
out.push(ffi::egl::CONFORMANT as c_int); out.push(ffi::egl::CONFORMANT as c_int);
out.push(ffi::egl::OPENGL_ES3_BIT as c_int); out.push(ffi::egl::OPENGL_ES3_BIT as c_int);
} }
(2, _) => { (2, _) => {
if egl_version < (1, 3) { if egl_version < (1, 3) {
error!(log, "OpenglES 2.* is not supported on EGL Versions lower then 1.3");
return Err(CreationError::NoAvailablePixelFormat); return Err(CreationError::NoAvailablePixelFormat);
} }
trace!(log, "Setting RENDERABLE_TYPE to OPENGL_ES2");
out.push(ffi::egl::RENDERABLE_TYPE as c_int); out.push(ffi::egl::RENDERABLE_TYPE as c_int);
out.push(ffi::egl::OPENGL_ES2_BIT as c_int); out.push(ffi::egl::OPENGL_ES2_BIT as c_int);
trace!(log, "Setting CONFORMANT to OPENGL_ES2");
out.push(ffi::egl::CONFORMANT as c_int); out.push(ffi::egl::CONFORMANT as c_int);
out.push(ffi::egl::OPENGL_ES2_BIT as c_int); out.push(ffi::egl::OPENGL_ES2_BIT as c_int);
} }
@ -285,46 +320,52 @@ impl EGLContext {
if let Some(hardware_accelerated) = reqs.hardware_accelerated { if let Some(hardware_accelerated) = reqs.hardware_accelerated {
out.push(ffi::egl::CONFIG_CAVEAT as c_int); out.push(ffi::egl::CONFIG_CAVEAT as c_int);
out.push(if hardware_accelerated { out.push(if hardware_accelerated {
trace!(log, "Setting CONFIG_CAVEAT to NONE");
ffi::egl::NONE as c_int ffi::egl::NONE as c_int
} else { } else {
trace!(log, "Setting CONFIG_CAVEAT to SLOW_CONFIG");
ffi::egl::SLOW_CONFIG as c_int ffi::egl::SLOW_CONFIG as c_int
}); });
} }
if let Some(color) = reqs.color_bits { if let Some(color) = reqs.color_bits {
trace!(log, "Setting RED_SIZE to {}", color / 3);
out.push(ffi::egl::RED_SIZE as c_int); out.push(ffi::egl::RED_SIZE as c_int);
out.push((color / 3) as c_int); out.push((color / 3) as c_int);
trace!(log, "Setting GREEN_SIZE to {}", color / 3 + if color % 3 != 0 { 1 } else { 0 });
out.push(ffi::egl::GREEN_SIZE as c_int); out.push(ffi::egl::GREEN_SIZE as c_int);
out.push((color / 3 + if color % 3 != 0 { 1 } else { 0 }) as c_int); out.push((color / 3 + if color % 3 != 0 { 1 } else { 0 }) as c_int);
trace!(log, "Setting BLUE_SIZE to {}", color / 3 + if color % 3 == 2 { 1 } else { 0 });
out.push(ffi::egl::BLUE_SIZE as c_int); out.push(ffi::egl::BLUE_SIZE as c_int);
out.push((color / 3 + if color % 3 == 2 { 1 } else { 0 }) as c_int); out.push((color / 3 + if color % 3 == 2 { 1 } else { 0 }) as c_int);
} }
if let Some(alpha) = reqs.alpha_bits { if let Some(alpha) = reqs.alpha_bits {
trace!(log, "Setting ALPHA_SIZE to {}", alpha);
out.push(ffi::egl::ALPHA_SIZE as c_int); out.push(ffi::egl::ALPHA_SIZE as c_int);
out.push(alpha as c_int); out.push(alpha as c_int);
} }
if let Some(depth) = reqs.depth_bits { if let Some(depth) = reqs.depth_bits {
trace!(log, "Setting DEPTH_SIZE to {}", depth);
out.push(ffi::egl::DEPTH_SIZE as c_int); out.push(ffi::egl::DEPTH_SIZE as c_int);
out.push(depth as c_int); out.push(depth as c_int);
} }
if let Some(stencil) = reqs.stencil_bits { if let Some(stencil) = reqs.stencil_bits {
trace!(log, "Setting STENCIL_SIZE to {}", stencil);
out.push(ffi::egl::STENCIL_SIZE as c_int); out.push(ffi::egl::STENCIL_SIZE as c_int);
out.push(stencil as c_int); out.push(stencil as c_int);
} }
if let Some(true) = reqs.double_buffer {
return Err(CreationError::NoAvailablePixelFormat);
}
if let Some(multisampling) = reqs.multisampling { if let Some(multisampling) = reqs.multisampling {
trace!(log, "Setting SAMPLES to {}", multisampling);
out.push(ffi::egl::SAMPLES as c_int); out.push(ffi::egl::SAMPLES as c_int);
out.push(multisampling as c_int); out.push(multisampling as c_int);
} }
if reqs.stereoscopy { if reqs.stereoscopy {
error!(log, "Stereoscopy is currently unsupported (sorry!)");
return Err(CreationError::NoAvailablePixelFormat); return Err(CreationError::NoAvailablePixelFormat);
} }
@ -343,6 +384,7 @@ impl EGLContext {
return Err(CreationError::OsError(String::from("eglChooseConfig failed"))); return Err(CreationError::OsError(String::from("eglChooseConfig failed")));
} }
if num_configs == 0 { if num_configs == 0 {
error!(log, "No matching color format found");
return Err(CreationError::NoAvailablePixelFormat); return Err(CreationError::NoAvailablePixelFormat);
} }
@ -379,15 +421,20 @@ impl EGLContext {
srgb: false, // TODO: use EGL_KHR_gl_colorspace to know that srgb: false, // TODO: use EGL_KHR_gl_colorspace to know that
}; };
info!(log, "Selected color format: {:?}", desc);
let mut context_attributes = Vec::with_capacity(10); let mut context_attributes = Vec::with_capacity(10);
if egl_version >= (1, 5) || extensions.iter().any(|s| s == &"EGL_KHR_create_context") { if egl_version >= (1, 5) || extensions.iter().any(|s| s == &"EGL_KHR_create_context") {
trace!(log, "Setting CONTEXT_MAJOR_VERSION to {}", version.0);
context_attributes.push(ffi::egl::CONTEXT_MAJOR_VERSION as i32); context_attributes.push(ffi::egl::CONTEXT_MAJOR_VERSION as i32);
context_attributes.push(version.0 as i32); context_attributes.push(version.0 as i32);
trace!(log, "Setting CONTEXT_MINOR_VERSION to {}", version.1);
context_attributes.push(ffi::egl::CONTEXT_MINOR_VERSION as i32); context_attributes.push(ffi::egl::CONTEXT_MINOR_VERSION as i32);
context_attributes.push(version.1 as i32); context_attributes.push(version.1 as i32);
if attributes.debug && egl_version >= (1, 5) { if attributes.debug && egl_version >= (1, 5) {
trace!(log, "Setting CONTEXT_OPENGL_DEBUG to TRUE");
context_attributes.push(ffi::egl::CONTEXT_OPENGL_DEBUG as i32); context_attributes.push(ffi::egl::CONTEXT_OPENGL_DEBUG as i32);
context_attributes.push(ffi::egl::TRUE as i32); context_attributes.push(ffi::egl::TRUE as i32);
} }
@ -396,26 +443,53 @@ impl EGLContext {
context_attributes.push(0); context_attributes.push(0);
} else if egl_version >= (1, 3) { } else if egl_version >= (1, 3) {
trace!(log, "Setting CONTEXT_CLIENT_VERSION to {}", version.0);
context_attributes.push(ffi::egl::CONTEXT_CLIENT_VERSION as i32); context_attributes.push(ffi::egl::CONTEXT_CLIENT_VERSION as i32);
context_attributes.push(version.0 as i32); context_attributes.push(version.0 as i32);
} }
context_attributes.push(ffi::egl::NONE as i32); context_attributes.push(ffi::egl::NONE as i32);
trace!(log, "Creating EGL context...");
let context = egl.CreateContext(display, config_id, ptr::null(), context_attributes.as_ptr()); let context = egl.CreateContext(display, config_id, ptr::null(), context_attributes.as_ptr());
if context.is_null() { if context.is_null() {
match egl.GetError() as u32 { match egl.GetError() as u32 {
ffi::egl::BAD_ATTRIBUTE => return Err(CreationError::OpenGlVersionNotSupported), ffi::egl::BAD_ATTRIBUTE => {
error!(log, "Context creation failed as one or more requirements could not be met. Try removing some gl attributes or pixel format requirements");
return Err(CreationError::OpenGlVersionNotSupported);
},
e => panic!("eglCreateContext failed: 0x{:x}", e), e => panic!("eglCreateContext failed: 0x{:x}", e),
} }
} }
debug!(log, "EGL context successfully created");
let surface_attributes = {
let mut out: Vec<c_int> = Vec::with_capacity(2);
match reqs.double_buffer {
Some(true) => {
trace!(log, "Setting RENDER_BUFFER to BACK_BUFFER");
out.push(ffi::egl::RENDER_BUFFER as c_int);
out.push(ffi::egl::BACK_BUFFER as c_int);
},
Some(false) => {
trace!(log, "Setting RENDER_BUFFER to SINGLE_BUFFER");
out.push(ffi::egl::RENDER_BUFFER as c_int);
out.push(ffi::egl::SINGLE_BUFFER as c_int);
},
None => {},
}
out
};
trace!(log, "Creating EGL window surface...");
let surface = { let surface = {
let surface = match native { let surface = match native {
Native::X11(_, window) | Native::X11(_, window) |
Native::Wayland(_, window) | Native::Wayland(_, window) |
Native::Gbm(_, window) => egl.CreateWindowSurface(display, config_id, window, ptr::null()), Native::Gbm(_, window) => egl.CreateWindowSurface(display, config_id, window, surface_attributes.as_ptr()),
}; };
if surface.is_null() { if surface.is_null() {
@ -423,7 +497,9 @@ impl EGLContext {
} }
surface surface
}; };
debug!(log, "EGL window surface successfully created");
info!(log, "EGL context created");
Ok(EGLContext { Ok(EGLContext {
_lib: lib, _lib: lib,
context: context as *const _, context: context as *const _,

View File

@ -25,6 +25,7 @@ use winit::os::unix::{WindowExt, get_x11_xconnection};
pub struct WinitGraphicsBackend { pub struct WinitGraphicsBackend {
window: Rc<Window>, window: Rc<Window>,
context: EGLContext, context: EGLContext,
logger: ::slog::Logger,
} }
/// Abstracted event loop of a `winit` `Window` implementing the `InputBackend` trait /// Abstracted event loop of a `winit` `Window` implementing the `InputBackend` trait
@ -39,50 +40,64 @@ pub struct WinitInputBackend {
seat: Seat, seat: Seat,
input_config: (), input_config: (),
handler: Option<Box<InputHandler<WinitInputBackend> + 'static>>, handler: Option<Box<InputHandler<WinitInputBackend> + 'static>>,
logger: ::slog::Logger,
} }
/// Create a new `WinitGraphicsBackend`, which implements the `EGLGraphicsBackend` /// Create a new `WinitGraphicsBackend`, which implements the `EGLGraphicsBackend`
/// graphics backend trait and a corresponding `WinitInputBackend`, which implements /// graphics backend trait and a corresponding `WinitInputBackend`, which implements
/// the `InputBackend` trait /// the `InputBackend` trait
pub fn init() -> Result<(WinitGraphicsBackend, WinitInputBackend), CreationError> { pub fn init<L>(logger: L) -> Result<(WinitGraphicsBackend, WinitInputBackend), CreationError>
where L: Into<Option<::slog::Logger>>
{
init_from_builder(WindowBuilder::new() init_from_builder(WindowBuilder::new()
.with_dimensions(1280, 800) .with_dimensions(1280, 800)
.with_title("Smithay") .with_title("Smithay")
.with_visibility(true)) .with_visibility(true), logger)
} }
/// Create a new `WinitGraphicsBackend`, which implements the `EGLGraphicsBackend` /// Create a new `WinitGraphicsBackend`, which implements the `EGLGraphicsBackend`
/// graphics backend trait, from a given `WindowBuilder` struct and a corresponding /// graphics backend trait, from a given `WindowBuilder` struct and a corresponding
/// `WinitInputBackend`, which implements the `InputBackend` trait /// `WinitInputBackend`, which implements the `InputBackend` trait
pub fn init_from_builder(builder: WindowBuilder) pub fn init_from_builder<L>(builder: WindowBuilder, logger: L)
-> Result<(WinitGraphicsBackend, WinitInputBackend), CreationError> { -> Result<(WinitGraphicsBackend, WinitInputBackend), CreationError>
where L: Into<Option<::slog::Logger>>
{
init_from_builder_with_gl_attr(builder, init_from_builder_with_gl_attr(builder,
GlAttributes { GlAttributes {
version: None, version: None,
profile: None, profile: None,
debug: cfg!(debug_assertions), debug: cfg!(debug_assertions),
vsync: true, vsync: true,
}) }, logger)
} }
/// Create a new `WinitGraphicsBackend`, which implements the `EGLGraphicsBackend` /// Create a new `WinitGraphicsBackend`, which implements the `EGLGraphicsBackend`
/// graphics backend trait, from a given `WindowBuilder` struct, as well as given /// graphics backend trait, from a given `WindowBuilder` struct, as well as given
/// `GlAttributes` for further customization of the rendering pipeline and a /// `GlAttributes` for further customization of the rendering pipeline and a
/// corresponding `WinitInputBackend`, which implements the `InputBackend` trait. /// corresponding `WinitInputBackend`, which implements the `InputBackend` trait.
pub fn init_from_builder_with_gl_attr(builder: WindowBuilder, attributes: GlAttributes) pub fn init_from_builder_with_gl_attr<L>(builder: WindowBuilder, attributes: GlAttributes, logger: L)
-> Result<(WinitGraphicsBackend, WinitInputBackend), CreationError> { -> Result<(WinitGraphicsBackend, WinitInputBackend), CreationError>
where L: Into<Option<::slog::Logger>>
{
let log = ::slog_or_stdlog(logger).new(o!("smithay_module" => "backend_winit"));
info!(log, "Initializing a winit backend");
let events_loop = EventsLoop::new(); let events_loop = EventsLoop::new();
let window = Rc::new(builder.build(&events_loop)?); let window = Rc::new(builder.build(&events_loop)?);
debug!(log, "Window created");
let (native, surface) = if let (Some(conn), Some(window)) = let (native, surface) = if let (Some(conn), Some(window)) =
(get_x11_xconnection(), window.get_xlib_window()) { (get_x11_xconnection(), window.get_xlib_window()) {
debug!(log, "Window is backed by X11");
(Native::X11(conn.display as *const _, window), None) (Native::X11(conn.display as *const _, window), None)
} else if let (Some(display), Some(surface)) = } else if let (Some(display), Some(surface)) =
(window.get_wayland_display(), window.get_wayland_client_surface()) { (window.get_wayland_display(), window.get_wayland_client_surface()) {
debug!(log, "Window is backed by Wayland");
let (w, h) = window.get_inner_size().unwrap(); let (w, h) = window.get_inner_size().unwrap();
let egl_surface = wegl::WlEglSurface::new(surface, w as i32, h as i32); let egl_surface = wegl::WlEglSurface::new(surface, w as i32, h as i32);
(Native::Wayland(display, egl_surface.ptr() as *const _), Some(egl_surface)) (Native::Wayland(display, egl_surface.ptr() as *const _), Some(egl_surface))
} else { } else {
error!(log, "Window is backed by an unsupported graphics framework");
return Err(CreationError::NotSupported); return Err(CreationError::NotSupported);
}; };
@ -94,10 +109,10 @@ pub fn init_from_builder_with_gl_attr(builder: WindowBuilder, attributes: GlAttr
color_bits: Some(24), color_bits: Some(24),
alpha_bits: Some(8), alpha_bits: Some(8),
..Default::default() ..Default::default()
}) { }, log.clone()) {
Ok(context) => context, Ok(context) => context,
Err(err) => { Err(err) => {
println!("EGLContext creation failed:\n{}", err); error!(log, "EGLContext creation failed:\n {}", err);
return Err(err); return Err(err);
} }
} }
@ -106,6 +121,7 @@ pub fn init_from_builder_with_gl_attr(builder: WindowBuilder, attributes: GlAttr
Ok((WinitGraphicsBackend { Ok((WinitGraphicsBackend {
window: window.clone(), window: window.clone(),
context: context, context: context,
logger: log.new(o!("smithay_winit_component" => "graphics")),
}, },
WinitInputBackend { WinitInputBackend {
events_loop: events_loop, events_loop: events_loop,
@ -121,6 +137,7 @@ pub fn init_from_builder_with_gl_attr(builder: WindowBuilder, attributes: GlAttr
}), }),
input_config: (), input_config: (),
handler: None, handler: None,
logger: log.new(o!("smithay_winit_component" => "input")),
})) }))
} }
@ -128,20 +145,25 @@ impl GraphicsBackend for WinitGraphicsBackend {
type CursorFormat = MouseCursor; type CursorFormat = MouseCursor;
fn set_cursor_position(&mut self, x: u32, y: u32) -> Result<(), ()> { fn set_cursor_position(&mut self, x: u32, y: u32) -> Result<(), ()> {
debug!(self.logger, "Setting cursor position to {:?}", (x, y));
self.window.set_cursor_position(x as i32, y as i32) self.window.set_cursor_position(x as i32, y as i32)
} }
fn set_cursor_representation(&mut self, cursor: Self::CursorFormat) { fn set_cursor_representation(&mut self, cursor: Self::CursorFormat) {
//Cannot log this one, as `CursorFormat` is not `Debug` and should not be
debug!(self.logger, "Changing cursor representation");
self.window.set_cursor(cursor) self.window.set_cursor(cursor)
} }
} }
impl EGLGraphicsBackend for WinitGraphicsBackend { impl EGLGraphicsBackend for WinitGraphicsBackend {
fn swap_buffers(&self) -> Result<(), SwapBuffersError> { fn swap_buffers(&self) -> Result<(), SwapBuffersError> {
trace!(self.logger, "Swapping buffers");
self.context.swap_buffers() self.context.swap_buffers()
} }
unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void { unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void {
trace!(self.logger, "Getting symbol for {:?}", symbol);
self.context.get_proc_address(symbol) self.context.get_proc_address(symbol)
} }
@ -156,6 +178,7 @@ impl EGLGraphicsBackend for WinitGraphicsBackend {
} }
unsafe fn make_current(&self) -> Result<(), SwapBuffersError> { unsafe fn make_current(&self) -> Result<(), SwapBuffersError> {
debug!(self.logger, "Making context the current one");
self.context.make_current() self.context.make_current()
} }
@ -448,6 +471,8 @@ impl InputBackend for WinitInputBackend {
if self.handler.is_some() { if self.handler.is_some() {
self.clear_handler(); self.clear_handler();
} }
info!(self.logger, "New input handler set.");
trace!(self.logger, "Calling on_seat_created with {:?}", self.seat);
handler.on_seat_created(&self.seat); handler.on_seat_created(&self.seat);
self.handler = Some(Box::new(handler)); self.handler = Some(Box::new(handler));
} }
@ -460,8 +485,10 @@ impl InputBackend for WinitInputBackend {
fn clear_handler(&mut self) { fn clear_handler(&mut self) {
if let Some(mut handler) = self.handler.take() { if let Some(mut handler) = self.handler.take() {
trace!(self.logger, "Calling on_seat_destroyed with {:?}", self.seat);
handler.on_seat_destroyed(&self.seat); handler.on_seat_destroyed(&self.seat);
} }
info!(self.logger, "Removing input handler");
} }
fn input_config(&mut self) -> &mut Self::InputConfig { fn input_config(&mut self) -> &mut Self::InputConfig {
@ -484,6 +511,11 @@ impl InputBackend for WinitInputBackend {
let mut closed = false; let mut closed = false;
{ {
// NOTE: This ugly pile of references is here, because rustc could
// figure out how to reference all these objects correctly into the
// upcoming closure, which is why all are borrowed manually and the
// assignments are then moved into the closure to avoid rustc's
// wrong interference.
let mut closed_ptr = &mut closed; let mut closed_ptr = &mut closed;
let mut key_counter = &mut self.key_counter; let mut key_counter = &mut self.key_counter;
let mut time_counter = &mut self.time_counter; let mut time_counter = &mut self.time_counter;
@ -491,12 +523,14 @@ impl InputBackend for WinitInputBackend {
let window = &self.window; let window = &self.window;
let surface = &self.surface; let surface = &self.surface;
let mut handler = self.handler.as_mut(); let mut handler = self.handler.as_mut();
let logger = &self.logger;
self.events_loop self.events_loop
.poll_events(move |event| match event { .poll_events(move |event| match event {
Event::WindowEvent { event, .. } => { Event::WindowEvent { event, .. } => {
match (event, handler.as_mut()) { match (event, handler.as_mut()) {
(WindowEvent::Resized(x, y), _) => { (WindowEvent::Resized(x, y), _) => {
trace!(logger, "Resizing window to {:?}", (x, y));
window.set_inner_size(x, y); window.set_inner_size(x, y);
if let Some(wl_egl_surface) = surface.as_ref() { if let Some(wl_egl_surface) = surface.as_ref() {
wl_egl_surface.resize(x as i32, y as i32, 0, 0); wl_egl_surface.resize(x as i32, y as i32, 0, 0);
@ -512,6 +546,7 @@ impl InputBackend for WinitInputBackend {
*key_counter = key_counter.checked_sub(1).unwrap_or(0) *key_counter = key_counter.checked_sub(1).unwrap_or(0)
} }
}; };
trace!(logger, "Calling on_keyboard_key with {:?}", (scancode, state));
handler.on_keyboard_key(seat, handler.on_keyboard_key(seat,
WinitKeyboardInputEvent { WinitKeyboardInputEvent {
time: *time_counter, time: *time_counter,
@ -522,6 +557,7 @@ impl InputBackend for WinitInputBackend {
} }
(WindowEvent::MouseMoved { position: (x, y), .. }, (WindowEvent::MouseMoved { position: (x, y), .. },
Some(handler)) => { Some(handler)) => {
trace!(logger, "Calling on_pointer_move_absolute with {:?}", (x, y));
handler.on_pointer_move_absolute(seat, handler.on_pointer_move_absolute(seat,
WinitMouseMovedEvent { WinitMouseMovedEvent {
window: window.clone(), window: window.clone(),
@ -531,24 +567,32 @@ impl InputBackend for WinitInputBackend {
}) })
} }
(WindowEvent::MouseWheel { delta, .. }, Some(handler)) => { (WindowEvent::MouseWheel { delta, .. }, Some(handler)) => {
let event = WinitMouseWheelEvent {
axis: Axis::Horizontal,
time: *time_counter,
delta: delta,
};
match delta { match delta {
MouseScrollDelta::LineDelta(x, y) | MouseScrollDelta::LineDelta(x, y) |
MouseScrollDelta::PixelDelta(x, y) => { MouseScrollDelta::PixelDelta(x, y) => {
if x != 0.0 { if x != 0.0 {
let event = WinitMouseWheelEvent {
axis: Axis::Horizontal,
time: *time_counter,
delta: delta,
};
trace!(logger, "Calling on_pointer_axis for Axis::Horizontal with {:?}", x);
handler.on_pointer_axis(seat, event); handler.on_pointer_axis(seat, event);
} }
if y != 0.0 { if y != 0.0 {
let event = WinitMouseWheelEvent {
axis: Axis::Vertical,
time: *time_counter,
delta: delta,
};
trace!(logger, "Calling on_pointer_axis for Axis::Vertical with {:?}", y);
handler.on_pointer_axis(seat, event); handler.on_pointer_axis(seat, event);
} }
} }
} }
} }
(WindowEvent::MouseInput { state, button, .. }, Some(handler)) => { (WindowEvent::MouseInput { state, button, .. }, Some(handler)) => {
trace!(logger, "Calling on_pointer_button with {:?}", (button, state));
handler.on_pointer_button(seat, handler.on_pointer_button(seat,
WinitMouseInputEvent { WinitMouseInputEvent {
time: *time_counter, time: *time_counter,
@ -563,6 +607,7 @@ impl InputBackend for WinitInputBackend {
.. ..
}), }),
Some(handler)) => { Some(handler)) => {
trace!(logger, "Calling on_touch_down at {:?}", (x, y));
handler.on_touch_down(seat, handler.on_touch_down(seat,
WinitTouchStartedEvent { WinitTouchStartedEvent {
window: window.clone(), window: window.clone(),
@ -578,6 +623,7 @@ impl InputBackend for WinitInputBackend {
.. ..
}), }),
Some(handler)) => { Some(handler)) => {
trace!(logger, "Calling on_touch_motion at {:?}", (x, y));
handler.on_touch_motion(seat, handler.on_touch_motion(seat,
WinitTouchMovedEvent { WinitTouchMovedEvent {
window: window.clone(), window: window.clone(),
@ -593,6 +639,7 @@ impl InputBackend for WinitInputBackend {
.. ..
}), }),
Some(handler)) => { Some(handler)) => {
trace!(logger, "Calling on_touch_motion at {:?}", (x, y));
handler.on_touch_motion(seat, handler.on_touch_motion(seat,
WinitTouchMovedEvent { WinitTouchMovedEvent {
window: window.clone(), window: window.clone(),
@ -600,6 +647,7 @@ impl InputBackend for WinitInputBackend {
location: (x, y), location: (x, y),
id: id, id: id,
}); });
trace!(logger, "Calling on_touch_up");
handler.on_touch_up(seat, handler.on_touch_up(seat,
WinitTouchEndedEvent { WinitTouchEndedEvent {
time: *time_counter, time: *time_counter,
@ -612,13 +660,17 @@ impl InputBackend for WinitInputBackend {
.. ..
}), }),
Some(handler)) => { Some(handler)) => {
trace!(logger, "Calling on_touch_cancel");
handler.on_touch_cancel(seat, handler.on_touch_cancel(seat,
WinitTouchCancelledEvent { WinitTouchCancelledEvent {
time: *time_counter, time: *time_counter,
id: id, id: id,
}) })
} },
(WindowEvent::Closed, _) => *closed_ptr = true, (WindowEvent::Closed, _) => {
warn!(logger, "Window closed");
*closed_ptr = true;
},
_ => {} _ => {}
} }
*time_counter += 1; *time_counter += 1;