From 2d255fd48d2c63a636157e4721f91d455a76ade9 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sat, 10 Jun 2017 22:59:59 +0200 Subject: [PATCH 1/8] Decouple EGLSurface from EGLContext --- Cargo.toml | 1 + src/backend/graphics/egl.rs | 182 +++++++++++++++++++++++------------- src/backend/winit.rs | 56 +++++++---- src/lib.rs | 2 + 4 files changed, 158 insertions(+), 83 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8d1df4d..8793c6a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ winit = { git = "https://github.com/tomaka/winit.git", optional = true } glium = { version = "~0.16.0", optional = true } input = { version = "~0.2.0", optional = true } clippy = { version = "*", optional = true } +rental = "0.4.11" [build-dependencies] gl_generator = "0.5" diff --git a/src/backend/graphics/egl.rs b/src/backend/graphics/egl.rs index 631c55a..87b352e 100644 --- a/src/backend/graphics/egl.rs +++ b/src/backend/graphics/egl.rs @@ -10,6 +10,7 @@ use super::GraphicsBackend; use libloading::Library; use nix::{c_int, c_void}; +use slog; use std::error::{self, Error}; use std::ffi::{CStr, CString}; @@ -17,6 +18,7 @@ use std::fmt; use std::io; use std::mem; use std::ptr; +use std::ops::Deref; #[allow(non_camel_case_types, dead_code)] mod ffi { @@ -44,16 +46,28 @@ mod ffi { /// Native types to create an `EGLContext` from. /// Currently supported providers are X11, Wayland and GBM. #[derive(Clone, Copy)] -pub enum Native { - /// X11 Display and Window objects to create an `EGLContext` upon. - X11(ffi::NativeDisplayType, ffi::NativeWindowType), - /// Wayland Display and Surface objects to create an `EGLContext` upon. - Wayland(ffi::NativeDisplayType, ffi::NativeWindowType), +pub enum NativeDisplay { + /// X11 Display to create an `EGLContext` upon. + X11(ffi::NativeDisplayType), + /// Wayland Display to create an `EGLContext` upon. + Wayland(ffi::NativeDisplayType), /// GBM Display - Gbm(ffi::NativeDisplayType, ffi::NativeWindowType), + Gbm(ffi::NativeDisplayType), } -/// Error that can happen while creating an `EGLContext` +/// Native types to create an `EGLSurface` from. +/// Currently supported providers are X11, Wayland and GBM. +#[derive(Clone, Copy)] +pub enum NativeSurface { + /// X11 Window to create an `EGLSurface` upon. + X11(ffi::NativeWindowType), + /// Wayland Surface to create an `EGLSurface` upon. + Wayland(ffi::NativeWindowType), + /// GBM Surface + Gbm(ffi::NativeWindowType), +} + +/// Error that can happen while creating an `EGLContext` or `EGLSurface` #[derive(Debug)] pub enum CreationError { /// I/O error from the underlying system @@ -115,8 +129,23 @@ pub struct EGLContext { context: ffi::egl::types::EGLContext, display: ffi::egl::types::EGLDisplay, egl: ffi::egl::Egl, - surface: ffi::egl::types::EGLSurface, + config_id: ffi::egl::types::EGLConfig, + surface_attributes: Vec, pixel_format: PixelFormat, + logger: slog::Logger, +} + +/// EGL surface of a given egl context for rendering +pub struct EGLSurface<'a> { + context: &'a EGLContext, + surface: ffi::egl::types::EGLSurface, +} + +impl<'a> Deref for EGLSurface<'a> { + type Target = EGLContext; + fn deref(&self) -> &Self::Target { + self.context + } } impl EGLContext { @@ -124,9 +153,9 @@ impl EGLContext { /// /// # Unsafety /// - /// This method is marked unsafe, because the contents of `Native` cannot be verified and msy + /// This method is marked unsafe, because the contents of `NativeDisplay` cannot be verified and msy /// contain dangeling pointers are similar unsafe content - pub unsafe fn new(native: Native, mut attributes: GlAttributes, reqs: PixelFormatRequirements, + pub unsafe fn new(native: NativeDisplay, mut attributes: GlAttributes, reqs: PixelFormatRequirements, logger: L) -> Result where L: Into> @@ -196,31 +225,31 @@ impl EGLContext { let has_dp_extension = |e: &str| dp_extensions.iter().any(|s| s == e); let display = match native { - Native::X11(display, _) if has_dp_extension("EGL_KHR_platform_x11") && + NativeDisplay::X11(display) if has_dp_extension("EGL_KHR_platform_x11") && 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()) } - Native::X11(display, _) if has_dp_extension("EGL_EXT_platform_x11") && + NativeDisplay::X11(display) if has_dp_extension("EGL_EXT_platform_x11") && 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()) } - Native::Gbm(display, _) if has_dp_extension("EGL_KHR_platform_gbm") && + NativeDisplay::Gbm(display) if has_dp_extension("EGL_KHR_platform_gbm") && 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()) } - Native::Gbm(display, _) if has_dp_extension("EGL_MESA_platform_gbm") && + NativeDisplay::Gbm(display) if has_dp_extension("EGL_MESA_platform_gbm") && 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()) } - Native::Wayland(display, _) if has_dp_extension("EGL_KHR_platform_wayland") && + NativeDisplay::Wayland(display) if has_dp_extension("EGL_KHR_platform_wayland") && egl.GetPlatformDisplay.is_loaded() => { trace!(log, "EGL Display Initialization via EGL_KHR_platform_wayland"); @@ -229,7 +258,7 @@ impl EGLContext { ptr::null()) } - Native::Wayland(display, _) if has_dp_extension("EGL_EXT_platform_wayland") && + NativeDisplay::Wayland(display) if has_dp_extension("EGL_EXT_platform_wayland") && egl.GetPlatformDisplayEXT.is_loaded() => { trace!(log, "EGL Display Initialization via EGL_EXT_platform_wayland"); @@ -238,9 +267,9 @@ impl EGLContext { ptr::null()) } - Native::X11(display, _) | - Native::Gbm(display, _) | - Native::Wayland(display, _) => { + NativeDisplay::X11(display) | + NativeDisplay::Gbm(display) | + NativeDisplay::Wayland(display) => { trace!(log, "Default EGL Display Initialization via GetDisplay"); egl.GetDisplay(display as *mut _) } @@ -266,7 +295,6 @@ impl EGLContext { let p = CStr::from_ptr(egl.QueryString(display, ffi::egl::EXTENSIONS as i32)); let list = String::from_utf8(p.to_bytes().to_vec()).unwrap_or_else(|_| String::new()); list.split(' ').map(|e| e.to_string()).collect::>() - } else { vec![] }; @@ -497,49 +525,49 @@ impl EGLContext { out }; - trace!(log, "Creating EGL window surface..."); + info!(log, "EGL context created"); + + Ok(EGLContext { + _lib: lib, + context: context as *const _, + display: display as *const _, + egl: egl, + config_id: config_id, + surface_attributes: surface_attributes, + pixel_format: desc, + logger: log, + }) + } + + /// Creates a surface bound to the given egl context for rendering + /// + /// # Unsafety + /// + /// This method is marked unsafe, because the contents of `NativeSurface` cannot be verified and msy + /// contain dangeling pointers are similar unsafe content + pub unsafe fn create_surface<'a>(&'a self, native: NativeSurface) -> Result, CreationError> { + trace!(self.logger, "Creating EGL window surface..."); + let surface = { let surface = match native { - Native::X11(_, window) | - Native::Wayland(_, window) | - Native::Gbm(_, window) => { - egl.CreateWindowSurface(display, config_id, window, surface_attributes.as_ptr()) - } + NativeSurface::X11(window) | + NativeSurface::Wayland(window) | + NativeSurface::Gbm(window) => self.egl.CreateWindowSurface(self.display, self.config_id, window, self.surface_attributes.as_ptr()), }; if surface.is_null() { return Err(CreationError::OsError(String::from("eglCreateWindowSurface failed"))); } + surface }; - debug!(log, "EGL window surface successfully created"); - info!(log, "EGL context created"); - Ok(EGLContext { - _lib: lib, - context: context as *const _, - display: display as *const _, - egl: egl, - surface: surface as *const _, - pixel_format: desc, - }) - } + debug!(self.logger, "EGL window surface successfully created"); - /// Swaps buffers at the end of a frame. - pub fn swap_buffers(&self) -> Result<(), SwapBuffersError> { - let ret = unsafe { - self.egl - .SwapBuffers(self.display as *const _, self.surface as *const _) - }; - - if ret == 0 { - match unsafe { self.egl.GetError() } as u32 { - ffi::egl::CONTEXT_LOST => Err(SwapBuffersError::ContextLost), - err => panic!("eglSwapBuffers failed (eglGetError returned 0x{:x})", err), - } - } else { - Ok(()) - } + Ok(EGLSurface { + context: &self, + surface: surface, + }) } /// Returns the address of an OpenGL function. @@ -556,6 +584,30 @@ impl EGLContext { unsafe { self.egl.GetCurrentContext() == self.context as *const _ } } + /// Returns the pixel format of the main framebuffer of the context. + pub fn get_pixel_format(&self) -> PixelFormat { + self.pixel_format + } +} + +impl<'a> EGLSurface<'a> { + /// Swaps buffers at the end of a frame. + pub fn swap_buffers(&self) -> Result<(), SwapBuffersError> { + let ret = unsafe { + self.context.egl + .SwapBuffers(self.context.display as *const _, self.surface as *const _) + }; + + if ret == 0 { + match unsafe { self.context.egl.GetError() } as u32 { + ffi::egl::CONTEXT_LOST => Err(SwapBuffersError::ContextLost), + err => panic!("eglSwapBuffers failed (eglGetError returned 0x{:x})", err), + } + } else { + Ok(()) + } + } + /// Makes the OpenGL context the current context in the current thread. /// /// # Unsafety @@ -563,14 +615,14 @@ impl EGLContext { /// This function is marked unsafe, because the context cannot be made current /// on multiple threads. pub unsafe fn make_current(&self) -> Result<(), SwapBuffersError> { - let ret = self.egl - .MakeCurrent(self.display as *const _, + let ret = self.context.egl + .MakeCurrent(self.context.display as *const _, self.surface as *const _, self.surface as *const _, - self.context as *const _); + self.context.context as *const _); if ret == 0 { - match self.egl.GetError() as u32 { + match self.context.egl.GetError() as u32 { ffi::egl::CONTEXT_LOST => Err(SwapBuffersError::ContextLost), err => panic!("eglMakeCurrent failed (eglGetError returned 0x{:x})", err), } @@ -578,15 +630,12 @@ impl EGLContext { Ok(()) } } - - /// Returns the pixel format of the main framebuffer of the context. - pub fn get_pixel_format(&self) -> PixelFormat { - self.pixel_format - } } unsafe impl Send for EGLContext {} unsafe impl Sync for EGLContext {} +unsafe impl<'a> Send for EGLSurface<'a> {} +unsafe impl<'a> Sync for EGLSurface<'a> {} impl Drop for EGLContext { fn drop(&mut self) { @@ -595,13 +644,20 @@ impl Drop for EGLContext { // is still the current one self.egl .DestroyContext(self.display as *const _, self.context as *const _); - self.egl - .DestroySurface(self.display as *const _, self.surface as *const _); self.egl.Terminate(self.display as *const _); } } } +impl<'a> Drop for EGLSurface<'a> { + fn drop(&mut self) { + unsafe { + self.context.egl + .DestroySurface(self.context.display as *const _, self.surface as *const _); + } + } +} + /// Error that can happen when swapping buffers. #[derive(Debug, Clone)] pub enum SwapBuffersError { diff --git a/src/backend/winit.rs b/src/backend/winit.rs index e56e729..924b0c5 100644 --- a/src/backend/winit.rs +++ b/src/backend/winit.rs @@ -2,7 +2,7 @@ use backend::{SeatInternal, TouchSlotInternal}; use backend::graphics::GraphicsBackend; -use backend::graphics::egl::{CreationError, EGLContext, EGLGraphicsBackend, GlAttributes, Native, +use backend::graphics::egl::{CreationError, EGLContext, EGLGraphicsBackend, GlAttributes, NativeDisplay, NativeSurface, PixelFormat, PixelFormatRequirements, SwapBuffersError}; use backend::input::{Axis, AxisSource, Event as BackendEvent, InputBackend, InputHandler, KeyState, KeyboardKeyEvent, MouseButton, MouseButtonState, PointerAxisEvent, PointerButtonEvent, @@ -20,11 +20,25 @@ use winit::{CreationError as WinitCreationError, ElementState, Event, EventsLoop WindowBuilder, WindowEvent}; use winit::os::unix::{WindowExt, get_x11_xconnection}; +rental! { + mod egl { + use std::boxed::Box; + use ::backend::graphics::egl::{EGLContext, EGLSurface}; + + + #[rental(deref_suffix)] + pub struct RentEGL { + context: Box, + surface: EGLSurface<'context>, + } + } +} + /// Window with an active EGL Context created by `winit`. Implements the /// `EGLGraphicsBackend` graphics backend trait pub struct WinitGraphicsBackend { window: Rc, - context: EGLContext, + context: egl::RentEGL, logger: ::slog::Logger, } @@ -89,23 +103,22 @@ pub fn init_from_builder_with_gl_attr let window = Rc::new(builder.build(&events_loop)?); debug!(log, "Window created"); - let (native, surface) = if let (Some(conn), Some(window)) = - (get_x11_xconnection(), window.get_xlib_window()) { - debug!(log, "Window is backed by X11"); - (Native::X11(conn.display as *const _, window), None) - } else if let (Some(display), Some(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 egl_surface = wegl::WlEglSurface::new(surface, w as i32, h as i32); - (Native::Wayland(display, egl_surface.ptr() as *const _), Some(egl_surface)) - } else { - error!(log, "Window is backed by an unsupported graphics framework"); - return Err(CreationError::NotSupported); - }; + let (native_display, native_surface, surface) = + if let (Some(conn), Some(window)) = (get_x11_xconnection(), window.get_xlib_window()) { + debug!(log, "Window is backed by X11"); + (NativeDisplay::X11(conn.display as *const _), NativeSurface::X11(window), None) + } else if let (Some(display), Some(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 egl_surface = wegl::WlEglSurface::new(surface, w as i32, h as i32); + (NativeDisplay::Wayland(display), NativeSurface::Wayland(egl_surface.ptr() as *const _), Some(egl_surface)) + } else { + error!(log, "Window is backed by an unsupported graphics framework"); + return Err(CreationError::NotSupported) + }; let context = unsafe { - match EGLContext::new(native, + match EGLContext::new(native_display, attributes, PixelFormatRequirements { hardware_accelerated: Some(true), @@ -124,7 +137,10 @@ pub fn init_from_builder_with_gl_attr Ok((WinitGraphicsBackend { window: window.clone(), - context: context, + context: match egl::RentEGL::try_new(Box::new(context), move |context| unsafe { context.create_surface(native_surface) }) { + Ok(x) => x, + Err(::rental::TryNewError(err, _)) => return Err(err), + }, logger: log.new(o!("smithay_winit_component" => "graphics")), }, WinitInputBackend { @@ -163,7 +179,7 @@ impl GraphicsBackend for WinitGraphicsBackend { impl EGLGraphicsBackend for WinitGraphicsBackend { fn swap_buffers(&self) -> Result<(), SwapBuffersError> { trace!(self.logger, "Swapping buffers"); - self.context.swap_buffers() + self.context.rent(|surface| surface.swap_buffers()) } unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void { @@ -183,7 +199,7 @@ impl EGLGraphicsBackend for WinitGraphicsBackend { unsafe fn make_current(&self) -> Result<(), SwapBuffersError> { debug!(self.logger, "Setting EGL context to be the current context"); - self.context.make_current() + self.context.rent(|surface| surface.make_current()) } fn get_pixel_format(&self) -> PixelFormat { diff --git a/src/lib.rs b/src/lib.rs index d29f3c9..f8befad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,8 @@ extern crate wayland_server; extern crate nix; extern crate xkbcommon; extern crate tempfile; +#[macro_use] +extern crate rental; #[cfg(feature = "backend_winit")] extern crate winit; From eef617258e20a33180d1911f47e5ea1a08faa1ae Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sat, 10 Jun 2017 23:29:09 +0200 Subject: [PATCH 2/8] rustfmt --- src/backend/graphics/egl.rs | 62 +++++++++++++++++++++---------------- src/backend/winit.rs | 37 ++++++++++++---------- 2 files changed, 57 insertions(+), 42 deletions(-) diff --git a/src/backend/graphics/egl.rs b/src/backend/graphics/egl.rs index 87b352e..5548085 100644 --- a/src/backend/graphics/egl.rs +++ b/src/backend/graphics/egl.rs @@ -17,8 +17,8 @@ use std::ffi::{CStr, CString}; use std::fmt; use std::io; use std::mem; -use std::ptr; use std::ops::Deref; +use std::ptr; #[allow(non_camel_case_types, dead_code)] mod ffi { @@ -155,8 +155,8 @@ impl EGLContext { /// /// This method is marked unsafe, because the contents of `NativeDisplay` cannot be verified and msy /// contain dangeling pointers are similar unsafe content - pub unsafe fn new(native: NativeDisplay, mut attributes: GlAttributes, reqs: PixelFormatRequirements, - logger: L) + pub unsafe fn new(native: NativeDisplay, mut attributes: GlAttributes, + reqs: PixelFormatRequirements, logger: L) -> Result where L: Into> { @@ -226,31 +226,31 @@ impl EGLContext { let display = match native { NativeDisplay::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()) } NativeDisplay::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()) } NativeDisplay::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()) } NativeDisplay::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()) } NativeDisplay::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, @@ -259,7 +259,7 @@ impl EGLContext { } NativeDisplay::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, @@ -528,15 +528,15 @@ impl EGLContext { info!(log, "EGL context created"); Ok(EGLContext { - _lib: lib, - context: context as *const _, - display: display as *const _, - egl: egl, - config_id: config_id, - surface_attributes: surface_attributes, - pixel_format: desc, - logger: log, - }) + _lib: lib, + context: context as *const _, + display: display as *const _, + egl: egl, + config_id: config_id, + surface_attributes: surface_attributes, + pixel_format: desc, + logger: log, + }) } /// Creates a surface bound to the given egl context for rendering @@ -545,14 +545,21 @@ impl EGLContext { /// /// This method is marked unsafe, because the contents of `NativeSurface` cannot be verified and msy /// contain dangeling pointers are similar unsafe content - pub unsafe fn create_surface<'a>(&'a self, native: NativeSurface) -> Result, CreationError> { + pub unsafe fn create_surface<'a>(&'a self, native: NativeSurface) + -> Result, CreationError> { trace!(self.logger, "Creating EGL window surface..."); let surface = { let surface = match native { NativeSurface::X11(window) | NativeSurface::Wayland(window) | - NativeSurface::Gbm(window) => self.egl.CreateWindowSurface(self.display, self.config_id, window, self.surface_attributes.as_ptr()), + NativeSurface::Gbm(window) => { + self.egl + .CreateWindowSurface(self.display, + self.config_id, + window, + self.surface_attributes.as_ptr()) + } }; if surface.is_null() { @@ -565,9 +572,9 @@ impl EGLContext { debug!(self.logger, "EGL window surface successfully created"); Ok(EGLSurface { - context: &self, - surface: surface, - }) + context: &self, + surface: surface, + }) } /// Returns the address of an OpenGL function. @@ -594,7 +601,8 @@ impl<'a> EGLSurface<'a> { /// Swaps buffers at the end of a frame. pub fn swap_buffers(&self) -> Result<(), SwapBuffersError> { let ret = unsafe { - self.context.egl + self.context + .egl .SwapBuffers(self.context.display as *const _, self.surface as *const _) }; @@ -615,7 +623,8 @@ impl<'a> EGLSurface<'a> { /// This function is marked unsafe, because the context cannot be made current /// on multiple threads. pub unsafe fn make_current(&self) -> Result<(), SwapBuffersError> { - let ret = self.context.egl + let ret = self.context + .egl .MakeCurrent(self.context.display as *const _, self.surface as *const _, self.surface as *const _, @@ -652,7 +661,8 @@ impl Drop for EGLContext { impl<'a> Drop for EGLSurface<'a> { fn drop(&mut self) { unsafe { - self.context.egl + self.context + .egl .DestroySurface(self.context.display as *const _, self.surface as *const _); } } diff --git a/src/backend/winit.rs b/src/backend/winit.rs index 924b0c5..680ca67 100644 --- a/src/backend/winit.rs +++ b/src/backend/winit.rs @@ -2,8 +2,8 @@ use backend::{SeatInternal, TouchSlotInternal}; use backend::graphics::GraphicsBackend; -use backend::graphics::egl::{CreationError, EGLContext, EGLGraphicsBackend, GlAttributes, NativeDisplay, NativeSurface, - PixelFormat, PixelFormatRequirements, SwapBuffersError}; +use backend::graphics::egl::{CreationError, EGLContext, EGLGraphicsBackend, GlAttributes, NativeDisplay, + NativeSurface, PixelFormat, PixelFormatRequirements, SwapBuffersError}; use backend::input::{Axis, AxisSource, Event as BackendEvent, InputBackend, InputHandler, KeyState, KeyboardKeyEvent, MouseButton, MouseButtonState, PointerAxisEvent, PointerButtonEvent, PointerMotionAbsoluteEvent, Seat, SeatCapabilities, TouchCancelEvent, TouchDownEvent, @@ -103,19 +103,22 @@ pub fn init_from_builder_with_gl_attr let window = Rc::new(builder.build(&events_loop)?); debug!(log, "Window created"); - let (native_display, native_surface, surface) = - if let (Some(conn), Some(window)) = (get_x11_xconnection(), window.get_xlib_window()) { - debug!(log, "Window is backed by X11"); - (NativeDisplay::X11(conn.display as *const _), NativeSurface::X11(window), None) - } else if let (Some(display), Some(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 egl_surface = wegl::WlEglSurface::new(surface, w as i32, h as i32); - (NativeDisplay::Wayland(display), NativeSurface::Wayland(egl_surface.ptr() as *const _), Some(egl_surface)) - } else { - error!(log, "Window is backed by an unsupported graphics framework"); - return Err(CreationError::NotSupported) - }; + let (native_display, native_surface, surface) = if let (Some(conn), Some(window)) = + (get_x11_xconnection(), window.get_xlib_window()) { + debug!(log, "Window is backed by X11"); + (NativeDisplay::X11(conn.display as *const _), NativeSurface::X11(window), None) + } else if let (Some(display), Some(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 egl_surface = wegl::WlEglSurface::new(surface, w as i32, h as i32); + (NativeDisplay::Wayland(display), + NativeSurface::Wayland(egl_surface.ptr() as *const _), + Some(egl_surface)) + } else { + error!(log, "Window is backed by an unsupported graphics framework"); + return Err(CreationError::NotSupported); + }; let context = unsafe { match EGLContext::new(native_display, @@ -137,7 +140,9 @@ pub fn init_from_builder_with_gl_attr Ok((WinitGraphicsBackend { window: window.clone(), - context: match egl::RentEGL::try_new(Box::new(context), move |context| unsafe { context.create_surface(native_surface) }) { + context: match egl::RentEGL::try_new(Box::new(context), move |context| unsafe { + context.create_surface(native_surface) + }) { Ok(x) => x, Err(::rental::TryNewError(err, _)) => return Err(err), }, From 5155b4494640bf8514312f8c5c8f863b9e1d4864 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Thu, 15 Jun 2017 13:33:18 +0200 Subject: [PATCH 3/8] Check if surface type is matching context type --- src/backend/graphics/egl.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/backend/graphics/egl.rs b/src/backend/graphics/egl.rs index 5548085..487a296 100644 --- a/src/backend/graphics/egl.rs +++ b/src/backend/graphics/egl.rs @@ -67,6 +67,13 @@ pub enum NativeSurface { Gbm(ffi::NativeWindowType), } +#[derive(PartialEq)] +enum NativeType { + X11, + Wayland, + Gbm, +} + /// Error that can happen while creating an `EGLContext` or `EGLSurface` #[derive(Debug)] pub enum CreationError { @@ -78,6 +85,10 @@ pub enum CreationError { OpenGlVersionNotSupported, /// There is no pixel format available that fulfills all requirements NoAvailablePixelFormat, + /// Surface creation from an unsupport combination + /// + /// E.g creating a surface from an X11 window on a context created from a wayland display + NonMatchingSurfaceType, /// Context creation is not supported on this system NotSupported, } @@ -106,10 +117,13 @@ impl error::Error for CreationError { CreationError::OpenGlVersionNotSupported => { "The requested OpenGL version is not \ supported." - } + }, CreationError::NoAvailablePixelFormat => { "Couldn't find any pixel format that matches \ the criterias." + }, + CreationError::NonMatchingSurfaceType => { + "Surface type does not match the context type." } CreationError::NotSupported => "Context creation is not supported on the current window system", } @@ -132,6 +146,7 @@ pub struct EGLContext { config_id: ffi::egl::types::EGLConfig, surface_attributes: Vec, pixel_format: PixelFormat, + backend_type: NativeType, logger: slog::Logger, } @@ -535,6 +550,11 @@ impl EGLContext { config_id: config_id, surface_attributes: surface_attributes, pixel_format: desc, + backend_type: match native { + NativeDisplay::X11(_) => NativeType::X11, + NativeDisplay::Wayland(_) => NativeType::Wayland, + NativeDisplay::Gbm(_) => NativeType::Gbm, + }, logger: log, }) } @@ -549,6 +569,14 @@ impl EGLContext { -> Result, CreationError> { trace!(self.logger, "Creating EGL window surface..."); + match native { + NativeSurface::X11(_) if self.backend_type != NativeType::X11 => return Err(CreationError::NonMatchingSurfaceType), + NativeSurface::Wayland(_) if self.backend_type != NativeType::Wayland => return Err(CreationError::NonMatchingSurfaceType), + NativeSurface::Gbm(_) if self.backend_type != NativeType::Gbm => + return Err(CreationError::NonMatchingSurfaceType), + _ => {}, + }; + let surface = { let surface = match native { NativeSurface::X11(window) | From 40e49ad7e92bf26cc45ead88d6f0e4eb312552cf Mon Sep 17 00:00:00 2001 From: Drakulix Date: Thu, 15 Jun 2017 13:33:43 +0200 Subject: [PATCH 4/8] Fix typos --- src/backend/graphics/egl.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/backend/graphics/egl.rs b/src/backend/graphics/egl.rs index 487a296..6fe3d0a 100644 --- a/src/backend/graphics/egl.rs +++ b/src/backend/graphics/egl.rs @@ -168,8 +168,8 @@ impl EGLContext { /// /// # Unsafety /// - /// This method is marked unsafe, because the contents of `NativeDisplay` cannot be verified and msy - /// contain dangeling pointers are similar unsafe content + /// This method is marked unsafe, because the contents of `NativeDisplay` cannot be verified and may + /// contain dangling pointers or similar unsafe content pub unsafe fn new(native: NativeDisplay, mut attributes: GlAttributes, reqs: PixelFormatRequirements, logger: L) -> Result @@ -563,8 +563,8 @@ impl EGLContext { /// /// # Unsafety /// - /// This method is marked unsafe, because the contents of `NativeSurface` cannot be verified and msy - /// contain dangeling pointers are similar unsafe content + /// This method is marked unsafe, because the contents of `NativeSurface` cannot be verified and may + /// contain dangling pointers or similar unsafe content pub unsafe fn create_surface<'a>(&'a self, native: NativeSurface) -> Result, CreationError> { trace!(self.logger, "Creating EGL window surface..."); From 57833f2b2d3424a52b5102fa81d17e2e62a1ca9e Mon Sep 17 00:00:00 2001 From: Drakulix Date: Thu, 15 Jun 2017 13:34:01 +0200 Subject: [PATCH 5/8] Bugfix surface_attribute termination --- src/backend/graphics/egl.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/backend/graphics/egl.rs b/src/backend/graphics/egl.rs index 6fe3d0a..457564d 100644 --- a/src/backend/graphics/egl.rs +++ b/src/backend/graphics/egl.rs @@ -521,7 +521,7 @@ impl EGLContext { debug!(log, "EGL context successfully created"); let surface_attributes = { - let mut out: Vec = Vec::with_capacity(2); + let mut out: Vec = Vec::with_capacity(3); match reqs.double_buffer { Some(true) => { @@ -537,6 +537,7 @@ impl EGLContext { None => {} } + out.push(ffi::egl::NONE as i32); out }; From f70cc6bf55df63db35aa5b64c67ab10a0de3e3ad Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sun, 18 Jun 2017 19:20:23 +0200 Subject: [PATCH 6/8] rustfmt --- src/backend/graphics/egl.rs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/backend/graphics/egl.rs b/src/backend/graphics/egl.rs index 457564d..6c14ca7 100644 --- a/src/backend/graphics/egl.rs +++ b/src/backend/graphics/egl.rs @@ -117,14 +117,12 @@ impl error::Error for CreationError { CreationError::OpenGlVersionNotSupported => { "The requested OpenGL version is not \ supported." - }, + } CreationError::NoAvailablePixelFormat => { "Couldn't find any pixel format that matches \ the criterias." - }, - CreationError::NonMatchingSurfaceType => { - "Surface type does not match the context type." } + CreationError::NonMatchingSurfaceType => "Surface type does not match the context type.", CreationError::NotSupported => "Context creation is not supported on the current window system", } } @@ -571,11 +569,16 @@ impl EGLContext { trace!(self.logger, "Creating EGL window surface..."); match native { - NativeSurface::X11(_) if self.backend_type != NativeType::X11 => return Err(CreationError::NonMatchingSurfaceType), - NativeSurface::Wayland(_) if self.backend_type != NativeType::Wayland => return Err(CreationError::NonMatchingSurfaceType), - NativeSurface::Gbm(_) if self.backend_type != NativeType::Gbm => - return Err(CreationError::NonMatchingSurfaceType), - _ => {}, + NativeSurface::X11(_) if self.backend_type != NativeType::X11 => { + return Err(CreationError::NonMatchingSurfaceType) + } + NativeSurface::Wayland(_) if self.backend_type != NativeType::Wayland => { + return Err(CreationError::NonMatchingSurfaceType) + } + NativeSurface::Gbm(_) if self.backend_type != NativeType::Gbm => { + return Err(CreationError::NonMatchingSurfaceType) + } + _ => {} }; let surface = { From b131f8168e2f527377ed9a805effcfc0b9975d9d Mon Sep 17 00:00:00 2001 From: Drakulix Date: Tue, 20 Jun 2017 10:50:20 +0200 Subject: [PATCH 7/8] Shorten surface type matching --- src/backend/graphics/egl.rs | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/src/backend/graphics/egl.rs b/src/backend/graphics/egl.rs index 6c14ca7..54909b1 100644 --- a/src/backend/graphics/egl.rs +++ b/src/backend/graphics/egl.rs @@ -67,7 +67,7 @@ pub enum NativeSurface { Gbm(ffi::NativeWindowType), } -#[derive(PartialEq)] +#[derive(Clone, Copy, PartialEq)] enum NativeType { X11, Wayland, @@ -568,30 +568,18 @@ impl EGLContext { -> Result, CreationError> { trace!(self.logger, "Creating EGL window surface..."); - match native { - NativeSurface::X11(_) if self.backend_type != NativeType::X11 => { - return Err(CreationError::NonMatchingSurfaceType) - } - NativeSurface::Wayland(_) if self.backend_type != NativeType::Wayland => { - return Err(CreationError::NonMatchingSurfaceType) - } - NativeSurface::Gbm(_) if self.backend_type != NativeType::Gbm => { - return Err(CreationError::NonMatchingSurfaceType) - } - _ => {} - }; - let surface = { - let surface = match native { - NativeSurface::X11(window) | - NativeSurface::Wayland(window) | - NativeSurface::Gbm(window) => { + let surface = match (native, self.backend_type) { + (NativeSurface::X11(window), NativeType::X11) | + (NativeSurface::Wayland(window), NativeType::Wayland) | + (NativeSurface::Gbm(window), NativeType::Gbm) => { self.egl .CreateWindowSurface(self.display, self.config_id, window, self.surface_attributes.as_ptr()) } + _ => return Err(CreationError::NonMatchingSurfaceType), }; if surface.is_null() { From 206007f5a55c65e2cbd353e6a17e548dbbf429ff Mon Sep 17 00:00:00 2001 From: Drakulix Date: Tue, 20 Jun 2017 11:31:18 +0200 Subject: [PATCH 8/8] rustfmt 0.9 update --- build.rs | 39 +-- examples/simple.rs | 7 +- src/backend/graphics/egl.rs | 243 +++++++++------- src/backend/graphics/glium.rs | 6 +- src/backend/input.rs | 18 +- src/backend/libinput.rs | 113 +++++--- src/backend/winit.rs | 520 +++++++++++++++++++--------------- src/keyboard/mod.rs | 77 ++--- src/lib.rs | 9 +- src/shm/mod.rs | 51 ++-- src/shm/pool.rs | 70 ++--- 11 files changed, 648 insertions(+), 505 deletions(-) diff --git a/build.rs b/build.rs index 0295cf5..11b884e 100644 --- a/build.rs +++ b/build.rs @@ -12,22 +12,25 @@ fn main() { println!("cargo:rerun-if-changed=build.rs"); let mut file = File::create(&dest.join("egl_bindings.rs")).unwrap(); - Registry::new(Api::Egl, - (1, 5), - Profile::Core, - Fallbacks::All, - ["EGL_KHR_create_context", - "EGL_EXT_create_context_robustness", - "EGL_KHR_create_context_no_error", - "EGL_KHR_platform_x11", - "EGL_KHR_platform_android", - "EGL_KHR_platform_wayland", - "EGL_KHR_platform_gbm", - "EGL_EXT_platform_base", - "EGL_EXT_platform_x11", - "EGL_MESA_platform_gbm", - "EGL_EXT_platform_wayland", - "EGL_EXT_platform_device"]) - .write_bindings(gl_generator::StructGenerator, &mut file) - .unwrap(); + Registry::new( + Api::Egl, + (1, 5), + Profile::Core, + Fallbacks::All, + [ + "EGL_KHR_create_context", + "EGL_EXT_create_context_robustness", + "EGL_KHR_create_context_no_error", + "EGL_KHR_platform_x11", + "EGL_KHR_platform_android", + "EGL_KHR_platform_wayland", + "EGL_KHR_platform_gbm", + "EGL_EXT_platform_base", + "EGL_EXT_platform_x11", + "EGL_MESA_platform_gbm", + "EGL_EXT_platform_wayland", + "EGL_EXT_platform_device", + ], + ).write_bindings(gl_generator::StructGenerator, &mut file) + .unwrap(); } diff --git a/examples/simple.rs b/examples/simple.rs index 8ed83c9..ef264ef 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -17,9 +17,10 @@ fn main() { // Insert the ShmGlobal as a handler to your event loop // Here, we specify tha the standard Argb8888 and Xrgb8888 is the only supported. - let handler_id = - event_loop.add_handler_with_init(ShmGlobal::new(vec![], - None /* we don't provide a logger here */)); + let handler_id = event_loop.add_handler_with_init(ShmGlobal::new( + vec![], + None, /* we don't provide a logger here */ + )); // Register this handler to advertise a wl_shm global of version 1 let shm_global = event_loop.register_global::(handler_id, 1); diff --git a/src/backend/graphics/egl.rs b/src/backend/graphics/egl.rs index 54909b1..bfd33ad 100644 --- a/src/backend/graphics/egl.rs +++ b/src/backend/graphics/egl.rs @@ -168,10 +168,11 @@ impl EGLContext { /// /// This method is marked unsafe, because the contents of `NativeDisplay` cannot be verified and may /// contain dangling pointers or similar unsafe content - pub unsafe fn new(native: NativeDisplay, mut attributes: GlAttributes, - reqs: PixelFormatRequirements, logger: L) + pub unsafe fn new(native: NativeDisplay, mut attributes: GlAttributes, reqs: PixelFormatRequirements, + logger: L) -> Result - where L: Into> + where + L: Into>, { let logger = logger.into(); let log = ::slog_or_stdlog(logger.clone()).new(o!("smithay_module" => "renderer_egl")); @@ -196,27 +197,31 @@ impl EGLContext { } } Some((1, _)) => { - error!(log, - "OpenGLES 1.* is not supported by the EGL renderer backend"); + error!( + log, + "OpenGLES 1.* is not supported by the EGL renderer backend" + ); return Err(CreationError::OpenGlVersionNotSupported); } Some(version) => { - error!(log, - "OpenGLES {:?} is unknown and not supported by the EGL renderer backend", - version); + error!( + log, + "OpenGLES {:?} is unknown and not supported by the EGL renderer backend", + version + ); return Err(CreationError::OpenGlVersionNotSupported); } }; let lib = Library::new("libEGL.so.1")?; let egl = ffi::egl::Egl::load_with(|sym| { - let name = CString::new(sym).unwrap(); - let symbol = lib.get::<*mut c_void>(name.as_bytes()); - match symbol { - Ok(x) => *x as *const _, - Err(_) => ptr::null(), - } - }); + let name = CString::new(sym).unwrap(); + let symbol = lib.get::<*mut c_void>(name.as_bytes()); + match symbol { + Ok(x) => *x as *const _, + Err(_) => ptr::null(), + } + }); // the first step is to query the list of extensions without any display, if supported let dp_extensions = { @@ -238,46 +243,54 @@ impl EGLContext { let has_dp_extension = |e: &str| dp_extensions.iter().any(|s| s == e); let display = match native { - NativeDisplay::X11(display) if has_dp_extension("EGL_KHR_platform_x11") && - egl.GetPlatformDisplay.is_loaded() => { + NativeDisplay::X11(display) + if has_dp_extension("EGL_KHR_platform_x11") && 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()) } - NativeDisplay::X11(display) if has_dp_extension("EGL_EXT_platform_x11") && - egl.GetPlatformDisplayEXT.is_loaded() => { + NativeDisplay::X11(display) + if has_dp_extension("EGL_EXT_platform_x11") && 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()) } - NativeDisplay::Gbm(display) if has_dp_extension("EGL_KHR_platform_gbm") && - egl.GetPlatformDisplay.is_loaded() => { + NativeDisplay::Gbm(display) + if has_dp_extension("EGL_KHR_platform_gbm") && 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()) } - NativeDisplay::Gbm(display) if has_dp_extension("EGL_MESA_platform_gbm") && - egl.GetPlatformDisplayEXT.is_loaded() => { + NativeDisplay::Gbm(display) + if has_dp_extension("EGL_MESA_platform_gbm") && 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()) } - NativeDisplay::Wayland(display) if has_dp_extension("EGL_KHR_platform_wayland") && - egl.GetPlatformDisplay.is_loaded() => { - trace!(log, - "EGL Display Initialization via EGL_KHR_platform_wayland"); - egl.GetPlatformDisplay(ffi::egl::PLATFORM_WAYLAND_KHR, - display as *mut _, - ptr::null()) + NativeDisplay::Wayland(display) + if has_dp_extension("EGL_KHR_platform_wayland") && egl.GetPlatformDisplay.is_loaded() => { + trace!( + log, + "EGL Display Initialization via EGL_KHR_platform_wayland" + ); + egl.GetPlatformDisplay( + ffi::egl::PLATFORM_WAYLAND_KHR, + display as *mut _, + ptr::null(), + ) } - NativeDisplay::Wayland(display) if has_dp_extension("EGL_EXT_platform_wayland") && - egl.GetPlatformDisplayEXT.is_loaded() => { - trace!(log, - "EGL Display Initialization via EGL_EXT_platform_wayland"); - egl.GetPlatformDisplayEXT(ffi::egl::PLATFORM_WAYLAND_EXT, - display as *mut _, - ptr::null()) + NativeDisplay::Wayland(display) + if has_dp_extension("EGL_EXT_platform_wayland") && egl.GetPlatformDisplayEXT.is_loaded() => { + trace!( + log, + "EGL Display Initialization via EGL_EXT_platform_wayland" + ); + egl.GetPlatformDisplayEXT( + ffi::egl::PLATFORM_WAYLAND_EXT, + display as *mut _, + ptr::null(), + ) } NativeDisplay::X11(display) | @@ -315,8 +328,10 @@ impl EGLContext { info!(log, "EGL Extensions: {:?}", extensions); if egl_version >= (1, 2) && egl.BindAPI(ffi::egl::OPENGL_ES_API) == 0 { - error!(log, - "OpenGLES not supported by the underlying EGL implementation"); + error!( + log, + "OpenGLES not supported by the underlying EGL implementation" + ); return Err(CreationError::OpenGlVersionNotSupported); } @@ -339,8 +354,10 @@ impl EGLContext { match version { (3, _) => { if egl_version < (1, 3) { - error!(log, - "OpenglES 3.* is not supported on EGL Versions lower then 1.3"); + error!( + log, + "OpenglES 3.* is not supported on EGL Versions lower then 1.3" + ); return Err(CreationError::NoAvailablePixelFormat); } trace!(log, "Setting RENDERABLE_TYPE to OPENGL_ES3"); @@ -352,8 +369,10 @@ impl EGLContext { } (2, _) => { if egl_version < (1, 3) { - error!(log, - "OpenglES 2.* is not supported on EGL Versions lower then 1.3"); + error!( + log, + "OpenglES 2.* is not supported on EGL Versions lower then 1.3" + ); return Err(CreationError::NoAvailablePixelFormat); } trace!(log, "Setting RENDERABLE_TYPE to OPENGL_ES2"); @@ -369,26 +388,30 @@ impl EGLContext { if let Some(hardware_accelerated) = reqs.hardware_accelerated { out.push(ffi::egl::CONFIG_CAVEAT as c_int); out.push(if hardware_accelerated { - trace!(log, "Setting CONFIG_CAVEAT to NONE"); - ffi::egl::NONE as c_int - } else { - trace!(log, "Setting CONFIG_CAVEAT to SLOW_CONFIG"); - ffi::egl::SLOW_CONFIG as c_int - }); + trace!(log, "Setting CONFIG_CAVEAT to NONE"); + ffi::egl::NONE as c_int + } else { + trace!(log, "Setting CONFIG_CAVEAT to SLOW_CONFIG"); + ffi::egl::SLOW_CONFIG as c_int + }); } 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((color / 3) as c_int); - trace!(log, - "Setting GREEN_SIZE to {}", - color / 3 + if color % 3 != 0 { 1 } else { 0 }); + 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((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 }); + 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((color / 3 + if color % 3 == 2 { 1 } else { 0 }) as c_int); } @@ -429,12 +452,17 @@ impl EGLContext { // calling `eglChooseConfig` let mut config_id = mem::uninitialized(); let mut num_configs = mem::uninitialized(); - if egl.ChooseConfig(display, - descriptor.as_ptr(), - &mut config_id, - 1, - &mut num_configs) == 0 { - return Err(CreationError::OsError(String::from("eglChooseConfig failed"))); + if egl.ChooseConfig( + display, + descriptor.as_ptr(), + &mut config_id, + 1, + &mut num_configs, + ) == 0 + { + return Err(CreationError::OsError( + String::from("eglChooseConfig failed"), + )); } if num_configs == 0 { error!(log, "No matching color format found"); @@ -458,10 +486,10 @@ impl EGLContext { let desc = PixelFormat { hardware_accelerated: attrib!(egl, display, config_id, ffi::egl::CONFIG_CAVEAT) != - ffi::egl::SLOW_CONFIG as i32, + ffi::egl::SLOW_CONFIG as i32, color_bits: attrib!(egl, display, config_id, ffi::egl::RED_SIZE) as u8 + - attrib!(egl, display, config_id, ffi::egl::BLUE_SIZE) as u8 + - attrib!(egl, display, config_id, ffi::egl::GREEN_SIZE) as u8, + attrib!(egl, display, config_id, ffi::egl::BLUE_SIZE) as u8 + + attrib!(egl, display, config_id, ffi::egl::GREEN_SIZE) as u8, alpha_bits: attrib!(egl, display, config_id, ffi::egl::ALPHA_SIZE) as u8, depth_bits: attrib!(egl, display, config_id, ffi::egl::DEPTH_SIZE) as u8, stencil_bits: attrib!(egl, display, config_id, ffi::egl::STENCIL_SIZE) as u8, @@ -509,8 +537,10 @@ impl EGLContext { if context.is_null() { match egl.GetError() as u32 { 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"); + 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), @@ -542,20 +572,20 @@ impl EGLContext { info!(log, "EGL context created"); Ok(EGLContext { - _lib: lib, - context: context as *const _, - display: display as *const _, - egl: egl, - config_id: config_id, - surface_attributes: surface_attributes, - pixel_format: desc, - backend_type: match native { - NativeDisplay::X11(_) => NativeType::X11, - NativeDisplay::Wayland(_) => NativeType::Wayland, - NativeDisplay::Gbm(_) => NativeType::Gbm, - }, - logger: log, - }) + _lib: lib, + context: context as *const _, + display: display as *const _, + egl: egl, + config_id: config_id, + surface_attributes: surface_attributes, + pixel_format: desc, + backend_type: match native { + NativeDisplay::X11(_) => NativeType::X11, + NativeDisplay::Wayland(_) => NativeType::Wayland, + NativeDisplay::Gbm(_) => NativeType::Gbm, + }, + logger: log, + }) } /// Creates a surface bound to the given egl context for rendering @@ -573,17 +603,20 @@ impl EGLContext { (NativeSurface::X11(window), NativeType::X11) | (NativeSurface::Wayland(window), NativeType::Wayland) | (NativeSurface::Gbm(window), NativeType::Gbm) => { - self.egl - .CreateWindowSurface(self.display, - self.config_id, - window, - self.surface_attributes.as_ptr()) + self.egl.CreateWindowSurface( + self.display, + self.config_id, + window, + self.surface_attributes.as_ptr(), + ) } _ => return Err(CreationError::NonMatchingSurfaceType), }; if surface.is_null() { - return Err(CreationError::OsError(String::from("eglCreateWindowSurface failed"))); + return Err(CreationError::OsError( + String::from("eglCreateWindowSurface failed"), + )); } surface @@ -592,9 +625,9 @@ impl EGLContext { debug!(self.logger, "EGL window surface successfully created"); Ok(EGLSurface { - context: &self, - surface: surface, - }) + context: &self, + surface: surface, + }) } /// Returns the address of an OpenGL function. @@ -621,9 +654,10 @@ impl<'a> EGLSurface<'a> { /// Swaps buffers at the end of a frame. pub fn swap_buffers(&self) -> Result<(), SwapBuffersError> { let ret = unsafe { - self.context - .egl - .SwapBuffers(self.context.display as *const _, self.surface as *const _) + self.context.egl.SwapBuffers( + self.context.display as *const _, + self.surface as *const _, + ) }; if ret == 0 { @@ -643,12 +677,12 @@ impl<'a> EGLSurface<'a> { /// This function is marked unsafe, because the context cannot be made current /// on multiple threads. pub unsafe fn make_current(&self) -> Result<(), SwapBuffersError> { - let ret = self.context - .egl - .MakeCurrent(self.context.display as *const _, - self.surface as *const _, - self.surface as *const _, - self.context.context as *const _); + let ret = self.context.egl.MakeCurrent( + self.context.display as *const _, + self.surface as *const _, + self.surface as *const _, + self.context.context as *const _, + ); if ret == 0 { match self.context.egl.GetError() as u32 { @@ -671,8 +705,10 @@ impl Drop for EGLContext { unsafe { // we don't call MakeCurrent(0, 0) because we are not sure that the context // is still the current one - self.egl - .DestroyContext(self.display as *const _, self.context as *const _); + self.egl.DestroyContext( + self.display as *const _, + self.context as *const _, + ); self.egl.Terminate(self.display as *const _); } } @@ -681,9 +717,10 @@ impl Drop for EGLContext { impl<'a> Drop for EGLSurface<'a> { fn drop(&mut self) { unsafe { - self.context - .egl - .DestroySurface(self.context.display as *const _, self.surface as *const _); + self.context.egl.DestroySurface( + self.context.display as *const _, + self.surface as *const _, + ); } } } diff --git a/src/backend/graphics/glium.rs b/src/backend/graphics/glium.rs index 2105eed..a3629de 100644 --- a/src/backend/graphics/glium.rs +++ b/src/backend/graphics/glium.rs @@ -48,8 +48,10 @@ impl GliumGraphicsBackend { /// Note that destroying a `Frame` is immediate, even if vsync is enabled. #[inline] pub fn draw(&self) -> Frame { - Frame::new(self.context.clone(), - self.backend.get_framebuffer_dimensions()) + Frame::new( + self.context.clone(), + self.backend.get_framebuffer_dimensions(), + ) } } diff --git a/src/backend/input.rs b/src/backend/input.rs index c1e7874..cb8998a 100644 --- a/src/backend/input.rs +++ b/src/backend/input.rs @@ -49,7 +49,8 @@ impl ::std::cmp::PartialEq for Seat { impl ::std::hash::Hash for Seat { fn hash(&self, state: &mut H) - where H: ::std::hash::Hasher + where + H: ::std::hash::Hasher, { self.id.hash(state); } @@ -275,7 +276,10 @@ pub trait PointerMotionAbsoluteEvent: Event { /// Device position converted to the targets coordinate space. /// E.g. the focused output's resolution. fn position_transformed(&self, coordinate_space: (u32, u32)) -> (u32, u32) { - (self.x_transformed(coordinate_space.0), self.y_transformed(coordinate_space.1)) + ( + self.x_transformed(coordinate_space.0), + self.y_transformed(coordinate_space.1), + ) } /// Device x position converted to the targets coordinate space's width. @@ -336,7 +340,10 @@ pub trait TouchDownEvent: Event { /// Touch position converted into the target coordinate space. /// E.g. the focused output's resolution. fn position_transformed(&self, coordinate_space: (u32, u32)) -> (u32, u32) { - (self.x_transformed(coordinate_space.0), self.y_transformed(coordinate_space.1)) + ( + self.x_transformed(coordinate_space.0), + self.y_transformed(coordinate_space.1), + ) } /// Touch event's x-coordinate in the device's native coordinate space @@ -395,7 +402,10 @@ pub trait TouchMotionEvent: Event { /// Touch position converted into the target coordinate space. /// E.g. the focused output's resolution. fn position_transformed(&self, coordinate_space: (u32, u32)) -> (u32, u32) { - (self.x_transformed(coordinate_space.0), self.y_transformed(coordinate_space.1)) + ( + self.x_transformed(coordinate_space.0), + self.y_transformed(coordinate_space.1), + ) } /// Touch event's x-coordinate in the device's native coordinate space diff --git a/src/backend/libinput.rs b/src/backend/libinput.rs index a02628e..65ceb4e 100644 --- a/src/backend/libinput.rs +++ b/src/backend/libinput.rs @@ -26,7 +26,8 @@ impl LibinputInputBackend { /// Initialize a new `LibinputInputBackend` from a given already initialized libinput /// context. pub fn new(context: libinput::Libinput, logger: L) -> Self - where L: Into> + where + L: Into>, { let log = ::slog_or_stdlog(logger).new(o!("smithay_module" => "backend_libinput")); info!(log, "Initializing a libinput backend"); @@ -270,9 +271,9 @@ impl backend::InputBackend for LibinputInputBackend { } fn get_handler(&mut self) -> Option<&mut backend::InputHandler> { - self.handler - .as_mut() - .map(|handler| handler as &mut backend::InputHandler) + self.handler.as_mut().map(|handler| { + handler as &mut backend::InputHandler + }) } fn clear_handler(&mut self) { @@ -328,8 +329,8 @@ impl backend::InputBackend for LibinputInputBackend { Entry::Vacant(seat_entry) => { let mut hasher = DefaultHasher::default(); seat_entry.key().hash(&mut hasher); - let seat = seat_entry - .insert(backend::Seat::new(hasher.finish(), new_caps)); + let seat = + seat_entry.insert(backend::Seat::new(hasher.finish(), new_caps)); if let Some(ref mut handler) = self.handler { trace!(self.logger, "Calling on_seat_created with {:?}", seat); handler.on_seat_created(seat); @@ -378,7 +379,7 @@ impl backend::InputBackend for LibinputInputBackend { } else { panic!("Seat destroyed that was never created"); } - // it has, notify about updates + // it has, notify about updates } else if let Some(ref mut handler) = self.handler { let seat = self.seats[&device_seat]; trace!(self.logger, "Calling on_seat_changed with {:?}", seat); @@ -394,18 +395,20 @@ impl backend::InputBackend for LibinputInputBackend { use input::event::touch::*; if let Some(ref mut handler) = self.handler { let device_seat = touch_event.device().seat(); - let seat = &self.seats - .get(&device_seat) - .expect("Recieved touch event of non existing Seat"); + let seat = &self.seats.get(&device_seat).expect( + "Recieved touch event of non existing Seat", + ); match touch_event { TouchEvent::Down(down_event) => { trace!(self.logger, "Calling on_touch_down with {:?}", down_event); handler.on_touch_down(seat, down_event) } TouchEvent::Motion(motion_event) => { - trace!(self.logger, - "Calling on_touch_motion with {:?}", - motion_event); + trace!( + self.logger, + "Calling on_touch_motion with {:?}", + motion_event + ); handler.on_touch_motion(seat, motion_event) } TouchEvent::Up(up_event) => { @@ -413,9 +416,11 @@ impl backend::InputBackend for LibinputInputBackend { handler.on_touch_up(seat, up_event) } TouchEvent::Cancel(cancel_event) => { - trace!(self.logger, - "Calling on_touch_cancel with {:?}", - cancel_event); + trace!( + self.logger, + "Calling on_touch_cancel with {:?}", + cancel_event + ); handler.on_touch_cancel(seat, cancel_event) } TouchEvent::Frame(frame_event) => { @@ -431,9 +436,9 @@ impl backend::InputBackend for LibinputInputBackend { KeyboardEvent::Key(key_event) => { if let Some(ref mut handler) = self.handler { let device_seat = key_event.device().seat(); - let seat = &self.seats - .get(&device_seat) - .expect("Recieved key event of non existing Seat"); + let seat = &self.seats.get(&device_seat).expect( + "Recieved key event of non existing Seat", + ); trace!(self.logger, "Calling on_keyboard_key with {:?}", key_event); handler.on_keyboard_key(seat, key_event); } @@ -444,49 +449,63 @@ impl backend::InputBackend for LibinputInputBackend { use input::event::pointer::*; if let Some(ref mut handler) = self.handler { let device_seat = pointer_event.device().seat(); - let seat = &self.seats - .get(&device_seat) - .expect("Recieved pointer event of non existing Seat"); + let seat = &self.seats.get(&device_seat).expect( + "Recieved pointer event of non existing Seat", + ); match pointer_event { PointerEvent::Motion(motion_event) => { - trace!(self.logger, - "Calling on_pointer_move with {:?}", - motion_event); + trace!( + self.logger, + "Calling on_pointer_move with {:?}", + motion_event + ); handler.on_pointer_move(seat, motion_event); } PointerEvent::MotionAbsolute(motion_abs_event) => { - trace!(self.logger, - "Calling on_pointer_move_absolute with {:?}", - motion_abs_event); + trace!( + self.logger, + "Calling on_pointer_move_absolute with {:?}", + motion_abs_event + ); handler.on_pointer_move_absolute(seat, motion_abs_event); } PointerEvent::Axis(axis_event) => { let rc_axis_event = Rc::new(axis_event); if rc_axis_event.has_axis(Axis::Vertical) { - trace!(self.logger, - "Calling on_pointer_axis for Axis::Vertical with {:?}", - *rc_axis_event); - handler.on_pointer_axis(seat, - self::PointerAxisEvent { - axis: Axis::Vertical, - event: rc_axis_event.clone(), - }); + trace!( + self.logger, + "Calling on_pointer_axis for Axis::Vertical with {:?}", + *rc_axis_event + ); + handler.on_pointer_axis( + seat, + self::PointerAxisEvent { + axis: Axis::Vertical, + event: rc_axis_event.clone(), + }, + ); } if rc_axis_event.has_axis(Axis::Horizontal) { - trace!(self.logger, - "Calling on_pointer_axis for Axis::Horizontal with {:?}", - *rc_axis_event); - handler.on_pointer_axis(seat, - self::PointerAxisEvent { - axis: Axis::Horizontal, - event: rc_axis_event.clone(), - }); + trace!( + self.logger, + "Calling on_pointer_axis for Axis::Horizontal with {:?}", + *rc_axis_event + ); + handler.on_pointer_axis( + seat, + self::PointerAxisEvent { + axis: Axis::Horizontal, + event: rc_axis_event.clone(), + }, + ); } } PointerEvent::Button(button_event) => { - trace!(self.logger, - "Calling on_pointer_button with {:?}", - button_event); + trace!( + self.logger, + "Calling on_pointer_button with {:?}", + button_event + ); handler.on_pointer_button(seat, button_event); } } diff --git a/src/backend/winit.rs b/src/backend/winit.rs index 680ca67..e54ceb8 100644 --- a/src/backend/winit.rs +++ b/src/backend/winit.rs @@ -61,13 +61,16 @@ pub struct WinitInputBackend { /// graphics backend trait and a corresponding `WinitInputBackend`, which implements /// the `InputBackend` trait pub fn init(logger: L) -> Result<(WinitGraphicsBackend, WinitInputBackend), CreationError> - where L: Into> +where + L: Into>, { - init_from_builder(WindowBuilder::new() - .with_dimensions(1280, 800) - .with_title("Smithay") - .with_visibility(true), - logger) + init_from_builder( + WindowBuilder::new() + .with_dimensions(1280, 800) + .with_title("Smithay") + .with_visibility(true), + logger, + ) } /// Create a new `WinitGraphicsBackend`, which implements the `EGLGraphicsBackend` @@ -75,26 +78,30 @@ pub fn init(logger: L) -> Result<(WinitGraphicsBackend, WinitInputBackend), C /// `WinitInputBackend`, which implements the `InputBackend` trait pub fn init_from_builder(builder: WindowBuilder, logger: L) -> Result<(WinitGraphicsBackend, WinitInputBackend), CreationError> - where L: Into> +where + L: Into>, { - init_from_builder_with_gl_attr(builder, - GlAttributes { - version: None, - profile: None, - debug: cfg!(debug_assertions), - vsync: true, - }, - logger) + init_from_builder_with_gl_attr( + builder, + GlAttributes { + version: None, + profile: None, + debug: cfg!(debug_assertions), + vsync: true, + }, + logger, + ) } /// Create a new `WinitGraphicsBackend`, which implements the `EGLGraphicsBackend` /// graphics backend trait, from a given `WindowBuilder` struct, as well as given /// `GlAttributes` for further customization of the rendering pipeline and a /// corresponding `WinitInputBackend`, which implements the `InputBackend` trait. -pub fn init_from_builder_with_gl_attr - (builder: WindowBuilder, attributes: GlAttributes, logger: L) - -> Result<(WinitGraphicsBackend, WinitInputBackend), CreationError> - where L: Into> +pub fn init_from_builder_with_gl_attr( + builder: WindowBuilder, attributes: GlAttributes, logger: L) + -> Result<(WinitGraphicsBackend, WinitInputBackend), CreationError> +where + L: Into>, { let log = ::slog_or_stdlog(logger).new(o!("smithay_module" => "backend_winit")); info!(log, "Initializing a winit backend"); @@ -103,33 +110,45 @@ pub fn init_from_builder_with_gl_attr let window = Rc::new(builder.build(&events_loop)?); debug!(log, "Window created"); - let (native_display, native_surface, surface) = if let (Some(conn), Some(window)) = - (get_x11_xconnection(), window.get_xlib_window()) { - debug!(log, "Window is backed by X11"); - (NativeDisplay::X11(conn.display as *const _), NativeSurface::X11(window), None) - } else if let (Some(display), Some(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 egl_surface = wegl::WlEglSurface::new(surface, w as i32, h as i32); - (NativeDisplay::Wayland(display), - NativeSurface::Wayland(egl_surface.ptr() as *const _), - Some(egl_surface)) - } else { - error!(log, "Window is backed by an unsupported graphics framework"); - return Err(CreationError::NotSupported); - }; + let (native_display, native_surface, surface) = + if let (Some(conn), Some(window)) = (get_x11_xconnection(), window.get_xlib_window()) { + debug!(log, "Window is backed by X11"); + ( + NativeDisplay::X11(conn.display as *const _), + NativeSurface::X11(window), + None, + ) + } else if let (Some(display), Some(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 egl_surface = wegl::WlEglSurface::new(surface, w as i32, h as i32); + ( + NativeDisplay::Wayland(display), + NativeSurface::Wayland(egl_surface.ptr() as *const _), + Some(egl_surface), + ) + } else { + error!(log, "Window is backed by an unsupported graphics framework"); + return Err(CreationError::NotSupported); + }; let context = unsafe { - match EGLContext::new(native_display, - attributes, - PixelFormatRequirements { - hardware_accelerated: Some(true), - color_bits: Some(24), - alpha_bits: Some(8), - ..Default::default() - }, - log.clone()) { + match EGLContext::new( + native_display, + attributes, + PixelFormatRequirements { + hardware_accelerated: Some(true), + color_bits: Some(24), + alpha_bits: Some(8), + ..Default::default() + }, + log.clone(), + ) { Ok(context) => context, Err(err) => { error!(log, "EGLContext creation failed:\n {}", err); @@ -138,11 +157,12 @@ pub fn init_from_builder_with_gl_attr } }; - Ok((WinitGraphicsBackend { + Ok(( + WinitGraphicsBackend { window: window.clone(), context: match egl::RentEGL::try_new(Box::new(context), move |context| unsafe { - context.create_surface(native_surface) - }) { + context.create_surface(native_surface) + }) { Ok(x) => x, Err(::rental::TryNewError(err, _)) => return Err(err), }, @@ -154,16 +174,19 @@ pub fn init_from_builder_with_gl_attr surface: surface, time_counter: 0, key_counter: 0, - seat: Seat::new(0, - SeatCapabilities { - pointer: true, - keyboard: true, - touch: true, - }), + seat: Seat::new( + 0, + SeatCapabilities { + pointer: true, + keyboard: true, + touch: true, + }, + ), input_config: (), handler: None, logger: log.new(o!("smithay_winit_component" => "input")), - })) + }, + )) } impl GraphicsBackend for WinitGraphicsBackend { @@ -193,9 +216,9 @@ impl EGLGraphicsBackend for WinitGraphicsBackend { } fn get_framebuffer_dimensions(&self) -> (u32, u32) { - self.window - .get_inner_size_pixels() - .expect("Window does not exist anymore") + self.window.get_inner_size_pixels().expect( + "Window does not exist anymore", + ) } fn is_current(&self) -> bool { @@ -288,16 +311,17 @@ impl PointerMotionAbsoluteEvent for WinitMouseMovedEvent { } fn x_transformed(&self, width: u32) -> u32 { - cmp::min((self.x * width as f64 / - self.window.get_inner_size_points().unwrap_or((width, 0)).0 as f64) as u32, - 0) + cmp::min( + (self.x * width as f64 / self.window.get_inner_size_points().unwrap_or((width, 0)).0 as f64) as u32, + 0, + ) } fn y_transformed(&self, height: u32) -> u32 { - cmp::min((self.y * height as f64 / - self.window.get_inner_size_points().unwrap_or((0, height)).1 as f64) as - u32, - 0) + cmp::min( + (self.y * height as f64 / self.window.get_inner_size_points().unwrap_or((0, height)).1 as f64) as u32, + 0, + ) } } @@ -390,15 +414,19 @@ impl TouchDownEvent for WinitTouchStartedEvent { } fn x_transformed(&self, width: u32) -> u32 { - cmp::min(self.location.0 as i32 * width as i32 / - self.window.get_inner_size_points().unwrap_or((width, 0)).0 as i32, - 0) as u32 + cmp::min( + self.location.0 as i32 * width as i32 / + self.window.get_inner_size_points().unwrap_or((width, 0)).0 as i32, + 0, + ) as u32 } fn y_transformed(&self, height: u32) -> u32 { - cmp::min(self.location.1 as i32 * height as i32 / - self.window.get_inner_size_points().unwrap_or((0, height)).1 as i32, - 0) as u32 + cmp::min( + self.location.1 as i32 * height as i32 / + self.window.get_inner_size_points().unwrap_or((0, height)).1 as i32, + 0, + ) as u32 } } @@ -503,16 +531,18 @@ impl InputBackend for WinitInputBackend { } fn get_handler(&mut self) -> Option<&mut InputHandler> { - self.handler - .as_mut() - .map(|handler| handler as &mut InputHandler) + self.handler.as_mut().map(|handler| { + handler as &mut InputHandler + }) } fn clear_handler(&mut self) { if let Some(mut handler) = self.handler.take() { - trace!(self.logger, - "Calling on_seat_destroyed with {:?}", - self.seat); + trace!( + self.logger, + "Calling on_seat_destroyed with {:?}", + self.seat + ); handler.on_seat_destroyed(&self.seat); } info!(self.logger, "Removing input handler"); @@ -552,168 +582,188 @@ impl InputBackend for WinitInputBackend { let mut handler = self.handler.as_mut(); let logger = &self.logger; - self.events_loop - .poll_events(move |event| match event { - Event::WindowEvent { event, .. } => { - match (event, handler.as_mut()) { - (WindowEvent::Resized(x, y), _) => { - trace!(logger, "Resizing window to {:?}", (x, y)); - window.set_inner_size(x, y); - if let Some(wl_egl_surface) = surface.as_ref() { - wl_egl_surface.resize(x as i32, y as i32, 0, 0); - } - } - (WindowEvent::KeyboardInput { - input: KeyboardInput { scancode, state, .. }, .. - }, - Some(handler)) => { - match state { - ElementState::Pressed => *key_counter += 1, - ElementState::Released => { - *key_counter = key_counter.checked_sub(1).unwrap_or(0) - } - }; - trace!(logger, - "Calling on_keyboard_key with {:?}", - (scancode, state)); - handler.on_keyboard_key(seat, - WinitKeyboardInputEvent { - time: *time_counter, - key: scancode, - count: *key_counter, - state: state, - }) - } - (WindowEvent::MouseMoved { position: (x, y), .. }, - Some(handler)) => { - trace!(logger, - "Calling on_pointer_move_absolute with {:?}", - (x, y)); - handler.on_pointer_move_absolute(seat, - WinitMouseMovedEvent { - window: window.clone(), - time: *time_counter, - x: x, - y: y, - }) - } - (WindowEvent::MouseWheel { delta, .. }, Some(handler)) => { - match delta { - MouseScrollDelta::LineDelta(x, y) | - MouseScrollDelta::PixelDelta(x, y) => { - 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); + self.events_loop.poll_events(move |event| match event { + Event::WindowEvent { event, .. } => { + match (event, handler.as_mut()) { + (WindowEvent::Resized(x, y), _) => { + trace!(logger, "Resizing window to {:?}", (x, y)); + window.set_inner_size(x, y); + if let Some(wl_egl_surface) = surface.as_ref() { + wl_egl_surface.resize(x as i32, y as i32, 0, 0); + } } - if y != 0.0 { - let event = WinitMouseWheelEvent { - axis: Axis::Vertical, - time: *time_counter, - delta: delta, + (WindowEvent::KeyboardInput { + input: KeyboardInput { scancode, state, .. }, .. + }, + Some(handler)) => { + match state { + ElementState::Pressed => *key_counter += 1, + ElementState::Released => { + *key_counter = key_counter.checked_sub(1).unwrap_or(0) + } }; - trace!(logger, - "Calling on_pointer_axis for Axis::Vertical with {:?}", - y); - handler.on_pointer_axis(seat, event); + trace!( + logger, + "Calling on_keyboard_key with {:?}", + (scancode, state) + ); + handler.on_keyboard_key( + seat, + WinitKeyboardInputEvent { + time: *time_counter, + key: scancode, + count: *key_counter, + state: state, + }, + ) } - } - } - } - (WindowEvent::MouseInput { state, button, .. }, Some(handler)) => { - trace!(logger, - "Calling on_pointer_button with {:?}", - (button, state)); - handler.on_pointer_button(seat, - WinitMouseInputEvent { - time: *time_counter, - button: button, - state: state, - }) - } - (WindowEvent::Touch(Touch { - phase: TouchPhase::Started, - location: (x, y), - id, - .. - }), - Some(handler)) => { - trace!(logger, "Calling on_touch_down at {:?}", (x, y)); - handler.on_touch_down(seat, - WinitTouchStartedEvent { - window: window.clone(), - time: *time_counter, - location: (x, y), - id: id, - }) - } - (WindowEvent::Touch(Touch { - phase: TouchPhase::Moved, - location: (x, y), - id, - .. - }), - Some(handler)) => { - trace!(logger, "Calling on_touch_motion at {:?}", (x, y)); - handler.on_touch_motion(seat, - WinitTouchMovedEvent { - window: window.clone(), - time: *time_counter, - location: (x, y), - id: id, - }) - } - (WindowEvent::Touch(Touch { - phase: TouchPhase::Ended, - location: (x, y), - id, - .. - }), - Some(handler)) => { - trace!(logger, "Calling on_touch_motion at {:?}", (x, y)); - handler.on_touch_motion(seat, - WinitTouchMovedEvent { - window: window.clone(), - time: *time_counter, - location: (x, y), - id: id, - }); - trace!(logger, "Calling on_touch_up"); - handler.on_touch_up(seat, - WinitTouchEndedEvent { - time: *time_counter, - id: id, - }); - } - (WindowEvent::Touch(Touch { - phase: TouchPhase::Cancelled, - id, - .. - }), - Some(handler)) => { - trace!(logger, "Calling on_touch_cancel"); - handler.on_touch_cancel(seat, - WinitTouchCancelledEvent { - time: *time_counter, - id: id, - }) - } - (WindowEvent::Closed, _) => { - warn!(logger, "Window closed"); - *closed_ptr = true; - } - _ => {} - } - *time_counter += 1; - } - Event::DeviceEvent { .. } => {} - }); + (WindowEvent::MouseMoved { position: (x, y), .. }, Some(handler)) => { + trace!(logger, "Calling on_pointer_move_absolute with {:?}", (x, y)); + handler.on_pointer_move_absolute( + seat, + WinitMouseMovedEvent { + window: window.clone(), + time: *time_counter, + x: x, + y: y, + }, + ) + } + (WindowEvent::MouseWheel { delta, .. }, Some(handler)) => { + match delta { + MouseScrollDelta::LineDelta(x, y) | + MouseScrollDelta::PixelDelta(x, y) => { + 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); + } + 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); + } + } + } + } + (WindowEvent::MouseInput { state, button, .. }, Some(handler)) => { + trace!( + logger, + "Calling on_pointer_button with {:?}", + (button, state) + ); + handler.on_pointer_button( + seat, + WinitMouseInputEvent { + time: *time_counter, + button: button, + state: state, + }, + ) + } + (WindowEvent::Touch(Touch { + phase: TouchPhase::Started, + location: (x, y), + id, + .. + }), + Some(handler)) => { + trace!(logger, "Calling on_touch_down at {:?}", (x, y)); + handler.on_touch_down( + seat, + WinitTouchStartedEvent { + window: window.clone(), + time: *time_counter, + location: (x, y), + id: id, + }, + ) + } + (WindowEvent::Touch(Touch { + phase: TouchPhase::Moved, + location: (x, y), + id, + .. + }), + Some(handler)) => { + trace!(logger, "Calling on_touch_motion at {:?}", (x, y)); + handler.on_touch_motion( + seat, + WinitTouchMovedEvent { + window: window.clone(), + time: *time_counter, + location: (x, y), + id: id, + }, + ) + } + (WindowEvent::Touch(Touch { + phase: TouchPhase::Ended, + location: (x, y), + id, + .. + }), + Some(handler)) => { + trace!(logger, "Calling on_touch_motion at {:?}", (x, y)); + handler.on_touch_motion( + seat, + WinitTouchMovedEvent { + window: window.clone(), + time: *time_counter, + location: (x, y), + id: id, + }, + ); + trace!(logger, "Calling on_touch_up"); + handler.on_touch_up( + seat, + WinitTouchEndedEvent { + time: *time_counter, + id: id, + }, + ); + } + (WindowEvent::Touch(Touch { + phase: TouchPhase::Cancelled, + id, + .. + }), + Some(handler)) => { + trace!(logger, "Calling on_touch_cancel"); + handler.on_touch_cancel( + seat, + WinitTouchCancelledEvent { + time: *time_counter, + id: id, + }, + ) + } + (WindowEvent::Closed, _) => { + warn!(logger, "Window closed"); + *closed_ptr = true; + } + _ => {} + } + *time_counter += 1; + } + Event::DeviceEvent { .. } => {} + }); } if closed { diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 883f5e8..cf957a9 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -37,7 +37,7 @@ pub use xkbcommon::xkb::{Keysym, keysyms}; /// /// For some modifiers, this means that the key is currently pressed, others are toggled /// (like caps lock). -#[derive(Copy,Clone,Debug)] +#[derive(Copy, Clone, Debug)] pub struct ModifiersState { /// The "control" key pub ctrl: bool, @@ -95,22 +95,23 @@ impl KbdInternal { // FIXME: This is an issue with the xkbcommon-rs crate that does not reflect this // non-threadsafety properly. let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS); - let keymap = xkb::Keymap::new_from_names(&context, - &rules, - &model, - &layout, - &variant, - options, - xkb::KEYMAP_COMPILE_NO_FLAGS) - .ok_or(())?; + let keymap = xkb::Keymap::new_from_names( + &context, + &rules, + &model, + &layout, + &variant, + options, + xkb::KEYMAP_COMPILE_NO_FLAGS, + ).ok_or(())?; let state = xkb::State::new(&keymap); Ok(KbdInternal { - focus: None, - pressed_keys: Vec::new(), - mods_state: ModifiersState::new(), - keymap: keymap, - state: state, - }) + focus: None, + pressed_keys: Vec::new(), + mods_state: ModifiersState::new(), + keymap: keymap, + state: state, + }) } // return true if modifier state has changed @@ -148,8 +149,10 @@ impl KbdInternal { fn serialize_pressed_keys(&self) -> Vec { let serialized = unsafe { - ::std::slice::from_raw_parts(self.pressed_keys.as_ptr() as *const u8, - self.pressed_keys.len() * 4) + ::std::slice::from_raw_parts( + self.pressed_keys.as_ptr() as *const u8, + self.pressed_keys.len() * 4, + ) }; serialized.into() } @@ -167,7 +170,8 @@ pub enum Error { pub fn create_keyboard_handler(rules: &str, model: &str, layout: &str, variant: &str, options: Option, logger: L) -> Result - where L: Into> +where + L: Into>, { let log = ::slog_or_stdlog(logger).new(o!("smithay_module" => "xkbcommon_handler")); info!(log, "Initializing a xkbcommon handler with keymap"; @@ -176,17 +180,17 @@ pub fn create_keyboard_handler(rules: &str, model: &str, layout: &str, varian ); let internal = KbdInternal::new(rules, model, layout, variant, options) .map_err(|_| { - debug!(log, "Loading keymap failed"); - Error::BadKeymap - })?; + debug!(log, "Loading keymap failed"); + Error::BadKeymap + })?; // prepare a tempfile with the keymap, to send it to clients let mut keymap_file = tempfile().map_err(Error::IoError)?; let keymap_data = internal.keymap.get_as_string(xkb::KEYMAP_FORMAT_TEXT_V1); - keymap_file - .write_all(keymap_data.as_bytes()) - .map_err(Error::IoError)?; + keymap_file.write_all(keymap_data.as_bytes()).map_err( + Error::IoError, + )?; keymap_file.flush().map_err(Error::IoError)?; trace!(log, "Keymap loaded and copied to tempfile."; @@ -194,13 +198,13 @@ pub fn create_keyboard_handler(rules: &str, model: &str, layout: &str, varian ); Ok(KbdHandle { - arc: Arc::new(KbdArc { - internal: Mutex::new(internal), - keymap_file: keymap_file, - keymap_len: keymap_data.as_bytes().len() as u32, - logger: log, - }), - }) + arc: Arc::new(KbdArc { + internal: Mutex::new(internal), + keymap_file: keymap_file, + keymap_len: keymap_data.as_bytes().len() as u32, + logger: log, + }), + }) } struct KbdArc { @@ -235,7 +239,8 @@ impl KbdHandle { /// The module `smithay::keyboard::keysyms` exposes definitions of all possible keysyms /// to be compared against. This includes non-characted keysyms, such as XF86 special keys. pub fn input(&self, keycode: u32, state: KeyState, serial: u32, filter: F) - where F: FnOnce(&ModifiersState, Keysym) -> bool + where + F: FnOnce(&ModifiersState, Keysym) -> bool, { trace!(self.arc.logger, "Handling keystroke"; "keycode" => keycode, "state" => format_args!("{:?}", state)); let mut guard = self.arc.internal.lock().unwrap(); @@ -315,8 +320,10 @@ impl KbdHandle { /// This should be done first, before anything else is done with this keyboard. pub fn send_keymap(&self, kbd: &wl_keyboard::WlKeyboard) { trace!(self.arc.logger, "Sending keymap to client"); - kbd.keymap(wl_keyboard::KeymapFormat::XkbV1, - self.arc.keymap_file.as_raw_fd(), - self.arc.keymap_len); + kbd.keymap( + wl_keyboard::KeymapFormat::XkbV1, + self.arc.keymap_file.as_raw_fd(), + self.arc.keymap_len, + ); } } diff --git a/src/lib.rs b/src/lib.rs index f8befad..3bfd660 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,10 +37,11 @@ pub mod backend; pub mod keyboard; fn slog_or_stdlog(logger: L) -> ::slog::Logger - where L: Into> +where + L: Into>, { use slog::Drain; - logger - .into() - .unwrap_or_else(|| ::slog::Logger::root(::slog_stdlog::StdLog.fuse(), o!())) + logger.into().unwrap_or_else(|| { + ::slog::Logger::root(::slog_stdlog::StdLog.fuse(), o!()) + }) } diff --git a/src/shm/mod.rs b/src/shm/mod.rs index a338004..bf9b873 100644 --- a/src/shm/mod.rs +++ b/src/shm/mod.rs @@ -89,7 +89,8 @@ impl ShmGlobal { /// as they are required by the protocol. Formats given as argument /// as additionnaly advertized. pub fn new(mut formats: Vec, logger: L) -> ShmGlobal - where L: Into> + where + L: Into>, { let log = ::slog_or_stdlog(logger); @@ -147,7 +148,8 @@ impl ShmGlobalToken { /// If the buffer is not managed by the associated ShmGlobal, the closure is not called /// and this method will return `Err(())` (this will be the case for an EGL buffer for example). pub fn with_buffer_contents(&self, buffer: &wl_buffer::WlBuffer, f: F) -> Result<(), BufferAccessError> - where F: FnOnce(&[u8], BufferData) + where + F: FnOnce(&[u8], BufferData), { if !resource_is_registered::<_, ShmHandler>(buffer, self.hid) { return Err(BufferAccessError::NotManaged); @@ -155,8 +157,9 @@ impl ShmGlobalToken { let data = unsafe { &*(buffer.get_user_data() as *mut InternalBufferData) }; if data.pool - .with_data_slice(|slice| f(slice, data.data)) - .is_err() { + .with_data_slice(|slice| f(slice, data.data)) + .is_err() + { // SIGBUS error occured buffer.post_error(wl_shm::Error::InvalidFd as u32, "Bad pool size.".into()); return Err(BufferAccessError::BadMap); @@ -168,10 +171,10 @@ impl ShmGlobalToken { impl Init for ShmGlobal { fn init(&mut self, evqh: &mut EventLoopHandle, _index: usize) { let id = evqh.add_handler_with_init(ShmHandler { - my_id: ::std::usize::MAX, - valid_formats: self.formats.clone(), - log: self.log.clone(), - }); + my_id: ::std::usize::MAX, + valid_formats: self.formats.clone(), + log: self.log.clone(), + }); self.handler_id = Some(id); } } @@ -205,8 +208,10 @@ impl wl_shm::Handler for ShmHandler { fn create_pool(&mut self, evqh: &mut EventLoopHandle, _client: &Client, shm: &wl_shm::WlShm, pool: wl_shm_pool::WlShmPool, fd: RawFd, size: i32) { if size <= 0 { - shm.post_error(wl_shm::Error::InvalidFd as u32, - "Invalid size for a new wl_shm_pool.".into()); + shm.post_error( + wl_shm::Error::InvalidFd as u32, + "Invalid size for a new wl_shm_pool.".into(), + ); return; } let mmap_pool = match Pool::new(fd, size as usize, self.log.clone()) { @@ -232,7 +237,7 @@ impl Destroy for ShmHandler { declare_handler!(ShmHandler, wl_shm::Handler, wl_shm::WlShm); /// Details of the contents of a buffer relative to its pool -#[derive(Copy,Clone,Debug)] +#[derive(Copy, Clone, Debug)] pub struct BufferData { /// Offset of the start of the buffer relative to the beginning of the pool in bytes pub offset: i32, @@ -261,15 +266,15 @@ impl wl_shm_pool::Handler for ShmHandler { } let arc_pool = unsafe { &*(pool.get_user_data() as *mut Arc) }; let data = Box::into_raw(Box::new(InternalBufferData { - pool: arc_pool.clone(), - data: BufferData { - offset: offset, - width: width, - height: height, - stride: stride, - format: format, - }, - })); + pool: arc_pool.clone(), + data: BufferData { + offset: offset, + width: width, + height: height, + stride: stride, + format: format, + }, + })); evqh.register_with_destructor::<_, ShmHandler, ShmHandler>(&buffer, self.my_id); buffer.set_user_data(data as *mut ()); } @@ -280,8 +285,10 @@ impl wl_shm_pool::Handler for ShmHandler { match arc_pool.resize(size) { Ok(()) => {} Err(ResizeError::InvalidSize) => { - pool.post_error(wl_shm::Error::InvalidFd as u32, - "Invalid new size for a wl_shm_pool.".into()); + pool.post_error( + wl_shm::Error::InvalidFd as u32, + "Invalid new size for a wl_shm_pool.".into(), + ); } Err(ResizeError::MremapFailed) => { pool.post_error(wl_shm::Error::InvalidFd as u32, "mremap failed.".into()); diff --git a/src/shm/pool.rs b/src/shm/pool.rs index 0056cc3..4a814f0 100644 --- a/src/shm/pool.rs +++ b/src/shm/pool.rs @@ -29,10 +29,10 @@ impl Pool { let memmap = MemMap::new(fd, size)?; trace!(log, "Creating new shm pool"; "fd" => fd as i32, "size" => size); Ok(Pool { - map: RwLock::new(memmap), - fd: fd, - log: log, - }) + map: RwLock::new(memmap), + fd: fd, + log: log, + }) } pub fn resize(&self, newsize: i32) -> Result<(), ResizeError> { @@ -51,8 +51,8 @@ impl Pool { pub fn with_data_slice(&self, f: F) -> Result<(), ()> { // Place the sigbus handler SIGBUS_INIT.call_once(|| unsafe { - place_sigbus_handler(); - }); + place_sigbus_handler(); + }); let pool_guard = self.map.read().unwrap(); @@ -60,13 +60,13 @@ impl Pool { // Prepare the access SIGBUS_GUARD.with(|guard| { - let (p, _) = guard.get(); - if !p.is_null() { - // Recursive call of this method is not supported - panic!("Recursive access to a SHM pool content is not supported."); - } - guard.set((&*pool_guard as *const MemMap, false)) - }); + let (p, _) = guard.get(); + if !p.is_null() { + // Recursive call of this method is not supported + panic!("Recursive access to a SHM pool content is not supported."); + } + guard.set((&*pool_guard as *const MemMap, false)) + }); let slice = pool_guard.get_slice(); f(slice); @@ -101,10 +101,10 @@ struct MemMap { impl MemMap { fn new(fd: RawFd, size: usize) -> Result { Ok(MemMap { - ptr: unsafe { map(fd, size) }?, - fd: fd, - size: size, - }) + ptr: unsafe { map(fd, size) }?, + fd: fd, + size: size, + }) } fn remap(&mut self, newsize: usize) -> Result<(), ()> { @@ -160,12 +160,14 @@ impl Drop for MemMap { // mman::mmap should really be unsafe... why isn't it? unsafe fn map(fd: RawFd, size: usize) -> Result<*mut u8, ()> { - let ret = mman::mmap(ptr::null_mut(), - size, - mman::PROT_READ, - mman::MAP_SHARED, - fd, - 0); + let ret = mman::mmap( + ptr::null_mut(), + size, + mman::PROT_READ, + mman::MAP_SHARED, + fd, + 0, + ); ret.map(|p| p as *mut u8).map_err(|_| ()) } @@ -176,20 +178,24 @@ unsafe fn unmap(ptr: *mut u8, size: usize) -> Result<(), ()> { } unsafe fn nullify_map(ptr: *mut u8, size: usize) -> Result<(), ()> { - let ret = mman::mmap(ptr as *mut _, - size, - mman::PROT_READ, - mman::MAP_ANONYMOUS | mman::MAP_PRIVATE | mman::MAP_FIXED, - -1, - 0); + let ret = mman::mmap( + ptr as *mut _, + size, + mman::PROT_READ, + mman::MAP_ANONYMOUS | mman::MAP_PRIVATE | mman::MAP_FIXED, + -1, + 0, + ); ret.map(|_| ()).map_err(|_| ()) } unsafe fn place_sigbus_handler() { // create our sigbus handler - let action = SigAction::new(SigHandler::SigAction(sigbus_handler), - signal::SA_NODEFER, - signal::SigSet::empty()); + let action = SigAction::new( + SigHandler::SigAction(sigbus_handler), + signal::SA_NODEFER, + signal::SigSet::empty(), + ); match signal::sigaction(Signal::SIGBUS, &action) { Ok(old_signal) => { OLD_SIGBUS_HANDLER = Box::into_raw(Box::new(old_signal));