diff --git a/examples/drm.rs b/examples/drm.rs index f6d1f25..f745dbd 100644 --- a/examples/drm.rs +++ b/examples/drm.rs @@ -27,7 +27,6 @@ use smithay::backend::graphics::egl::EGLGraphicsBackend; use smithay::backend::graphics::egl::wayland::{Format, EGLDisplay, EGLWaylandExtensions}; use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, TraversalAction}; use smithay::wayland::compositor::roles::Role; -use smithay::wayland::shell::ShellState; use smithay::wayland::shm::init_shm_global; use std::cell::RefCell; use std::fs::{File, OpenOptions}; @@ -35,7 +34,6 @@ use std::os::unix::io::RawFd; use std::os::unix::io::AsRawFd; use std::rc::Rc; use std::time::Duration; -use wayland_server::{StateToken}; #[derive(Debug)] pub struct Card(File); @@ -125,7 +123,7 @@ fn main() { init_shm_global(&mut event_loop, vec![], log.clone()); - let (compositor_token, shell_state_token, window_map) = init_shell(&mut event_loop, log.clone(), egl_display.clone()); + let (compositor_token, _shell_state_token, window_map) = init_shell(&mut event_loop, log.clone(), egl_display.clone()); /* * Add a listening socket: @@ -141,7 +139,6 @@ fn main() { &mut event_loop, device_token, DrmHandlerImpl { - shell_state_token, compositor_token, window_map: window_map.clone(), drawer: renderer, @@ -158,7 +155,6 @@ fn main() { } pub struct DrmHandlerImpl { - shell_state_token: StateToken>>, ()>>, compositor_token: CompositorToken>>>, window_map: Rc>, drawer: GliumDrawer>, diff --git a/examples/helpers/glium.rs b/examples/helpers/glium.rs index addaf1c..5c917da 100644 --- a/examples/helpers/glium.rs +++ b/examples/helpers/glium.rs @@ -1,16 +1,14 @@ use glium; use glium::{Frame, Surface, GlObject}; -use glium::backend::Facade; use glium::index::PrimitiveType; use glium::texture::{MipmapsOption, UncompressedFloatFormat, Texture2d}; use smithay::backend::graphics::egl::EGLGraphicsBackend; use smithay::backend::graphics::egl::error::Result as EGLResult; -use smithay::backend::graphics::egl::wayland::{Format, EGLImages, EGLDisplay, EGLWaylandExtensions, BufferAccessError}; +use smithay::backend::graphics::egl::wayland::{Format, EGLImages, EGLDisplay, EGLWaylandExtensions}; use smithay::backend::graphics::glium::GliumGraphicsBackend; use std::borrow::Borrow; use std::ops::Deref; use wayland_server::Display; -use wayland_server::protocol::wl_buffer::WlBuffer; #[derive(Copy, Clone)] struct Vertex { diff --git a/examples/udev.rs b/examples/udev.rs index 2aac748..0399757 100644 --- a/examples/udev.rs +++ b/examples/udev.rs @@ -19,7 +19,6 @@ extern crate ctrlc; mod helpers; -use drm::Device as BasicDevice; use drm::control::{Device as ControlDevice, ResourceInfo}; use drm::control::connector::{Info as ConnectorInfo, State as ConnectorState}; use drm::control::encoder::Info as EncoderInfo; @@ -45,7 +44,6 @@ use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, TraversalAct use smithay::wayland::compositor::roles::Role; use smithay::wayland::output::{Mode, Output, PhysicalProperties}; use smithay::wayland::seat::{KeyboardHandle, PointerHandle, Seat}; -use smithay::wayland::shell::ShellState; use smithay::wayland::shm::init_shm_global; use std::cell::RefCell; use std::collections::HashMap; @@ -56,7 +54,6 @@ use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Duration; use std::path::PathBuf; use std::process::Command; -use std::os::unix::io::{AsRawFd, RawFd}; use xkbcommon::xkb::keysyms as xkb; use wayland_server::{Display, StateToken, StateProxy}; use wayland_server::protocol::{wl_output, wl_pointer}; @@ -199,7 +196,7 @@ fn main() { */ init_shm_global(&mut event_loop, vec![], log.clone()); - let (compositor_token, shell_state_token, window_map) = init_shell(&mut event_loop, log.clone(), active_egl_context.clone()); + let (compositor_token, _shell_state_token, window_map) = init_shell(&mut event_loop, log.clone(), active_egl_context.clone()); /* * Initialize session on the current tty @@ -226,7 +223,6 @@ fn main() { let bytes = include_bytes!("resources/cursor2.rgba"); let udev_token = UdevBackend::new(&mut event_loop, &context, session.clone(), UdevHandlerImpl { - shell_state_token, compositor_token, active_egl_context, backends: HashMap::new(), @@ -307,9 +303,12 @@ fn main() { let udev_event_source = udev_backend_bind(&mut event_loop, udev_token).unwrap(); while running.load(Ordering::SeqCst) { - event_loop.dispatch(Some(16)); - display.flush_clients(); - window_map.borrow_mut().refresh(); + if let Err(_) = event_loop.dispatch(Some(16)) { + running.store(false, Ordering::SeqCst); + } else { + display.flush_clients(); + window_map.borrow_mut().refresh(); + } } println!("Bye Bye"); @@ -326,7 +325,6 @@ fn main() { } struct UdevHandlerImpl { - shell_state_token: StateToken>>, ()>>, compositor_token: CompositorToken>>>, active_egl_context: Rc>>, backends: HashMap>>>>>, @@ -399,7 +397,6 @@ impl UdevHandler for UdevHandlerImpl { self.backends.insert(device.device_id(), backends.clone()); Some(DrmHandlerImpl { - shell_state_token: self.shell_state_token.clone(), compositor_token: self.compositor_token.clone(), backends, window_map: self.window_map.clone(), @@ -434,7 +431,6 @@ impl UdevHandler for UdevHandlerImpl { } pub struct DrmHandlerImpl { - shell_state_token: StateToken>>, ()>>, compositor_token: CompositorToken>>>, backends: Rc>>>>, window_map: Rc>, diff --git a/src/backend/drm/backend.rs b/src/backend/drm/backend.rs index f7e8e98..a787663 100644 --- a/src/backend/drm/backend.rs +++ b/src/backend/drm/backend.rs @@ -14,6 +14,7 @@ use std::cell::Cell; use std::rc::{Rc, Weak}; use wayland_server::Display; +/// Backend based on a `DrmDevice` and a given crtc pub struct DrmBackend { backend: Rc>, surface: EGLSurface>, @@ -21,7 +22,6 @@ pub struct DrmBackend { connectors: Vec, } -/// Backend based on a `DrmDevice` and a given crtc pub(crate) struct DrmBackendInternal { context: Rc, GbmDevice>>, cursor: Cell>, diff --git a/src/backend/drm/mod.rs b/src/backend/drm/mod.rs index e29eaae..02717a8 100644 --- a/src/backend/drm/mod.rs +++ b/src/backend/drm/mod.rs @@ -400,7 +400,9 @@ impl DrmDevice { } } +/// Trait for types representing open devices pub trait DevPath { + /// Returns the path of the open device if possible fn dev_path(&self) -> Option; } @@ -556,7 +558,7 @@ where #[cfg(feature = "backend_session")] impl SessionObserver for StateToken> { fn pause<'a>(&mut self, state: &mut StateProxy<'a>) { - let device: &mut DrmDevice = state.get_mut(self); + let device = state.get_mut(self); device.active = false; if let Err(err) = device.drop_master() { error!( @@ -567,7 +569,7 @@ impl SessionObserver for StateToken> { } fn activate<'a>(&mut self, state: &mut StateProxy<'a>) { - let mut device = state.get_mut(self); + let device = state.get_mut(self); device.active = true; if let Err(err) = device.set_master() { crit!( diff --git a/src/backend/graphics/egl/context.rs b/src/backend/graphics/egl/context.rs index 9e84fd8..4d7413d 100644 --- a/src/backend/graphics/egl/context.rs +++ b/src/backend/graphics/egl/context.rs @@ -1,3 +1,5 @@ +//! EGL context related structs + use super::{ffi, EGLSurface, PixelFormat}; use super::error::*; use super::native; @@ -47,6 +49,7 @@ impl> DerefMut for EGLContext> EGLContext { + /// Create a new `EGLContext` from a given `NativeDisplay` pub fn new( native: N, attributes: GlAttributes, @@ -146,16 +149,16 @@ impl> EGLContext { Err(_) => ptr::null(), } }); - let procAddress = constrain(|sym| { + let proc_address = constrain(|sym| { let addr = CString::new(sym).unwrap(); let addr = addr.as_ptr(); ffi::egl::GetProcAddress(addr) as *const _ }); - ffi::egl::load_with(&procAddress); - ffi::egl::BindWaylandDisplayWL::load_with(&procAddress); - ffi::egl::UnbindWaylandDisplayWL::load_with(&procAddress); - ffi::egl::QueryWaylandBufferWL::load_with(&procAddress); - ffi::gl::load_with(&procAddress); + ffi::egl::load_with(&proc_address); + ffi::egl::BindWaylandDisplayWL::load_with(&proc_address); + ffi::egl::UnbindWaylandDisplayWL::load_with(&proc_address); + ffi::egl::QueryWaylandBufferWL::load_with(&proc_address); + ffi::gl::load_with(&proc_address); }); // the first step is to query the list of extensions without any display, if supported diff --git a/src/backend/graphics/egl/error.rs b/src/backend/graphics/egl/error.rs index 5c9419e..7823922 100644 --- a/src/backend/graphics/egl/error.rs +++ b/src/backend/graphics/egl/error.rs @@ -1,3 +1,5 @@ +//! EGL error types + error_chain! { errors { #[doc = "The requested OpenGL version is not supported"] diff --git a/src/backend/graphics/egl/mod.rs b/src/backend/graphics/egl/mod.rs index c3f583c..82abd4b 100644 --- a/src/backend/graphics/egl/mod.rs +++ b/src/backend/graphics/egl/mod.rs @@ -1,4 +1,4 @@ -//! Common traits and types for egl context creation and rendering +//! Common traits and types for egl rendering /// Large parts of this module are taken from /// https://github.com/tomaka/glutin/tree/044e651edf67a2029eecc650dd42546af1501414/src/api/egl/ diff --git a/src/backend/graphics/egl/native.rs b/src/backend/graphics/egl/native.rs index 05848c3..910320e 100644 --- a/src/backend/graphics/egl/native.rs +++ b/src/backend/graphics/egl/native.rs @@ -1,3 +1,5 @@ +//! Type safe native types for safe context/surface creation + use super::ffi; use super::error::*; @@ -18,9 +20,17 @@ use winit::os::unix::WindowExt; #[cfg(feature = "backend_winit")] use wayland_client::egl as wegl; +/// Trait for typed backend variants (X11/Wayland/GBM) pub trait Backend { + /// Surface type created by this backend type Surface: NativeSurface; + /// Return an `EGLDisplay` based on this backend + /// + /// # Unsafety + /// + /// The returned `EGLDisplay` needs to be a valid ptr for egl, + /// but there is no way to test that. unsafe fn get_display bool>( display: ffi::NativeDisplayType, has_dp_extension: F, @@ -29,6 +39,7 @@ pub trait Backend { } #[cfg(feature = "backend_winit")] +/// Wayland backend type pub enum Wayland {} #[cfg(feature = "backend_winit")] impl Backend for Wayland { @@ -65,8 +76,10 @@ impl Backend for Wayland { } #[cfg(feature = "backend_winit")] +/// Typed Xlib window for the `X11` backend pub struct XlibWindow(u64); #[cfg(feature = "backend_winit")] +/// X11 backend type pub enum X11 {} #[cfg(feature = "backend_winit")] impl Backend for X11 { @@ -94,6 +107,7 @@ impl Backend for X11 { } } #[cfg(feature = "backend_drm")] +/// Gbm backend type pub struct Gbm { _userdata: PhantomData, } @@ -134,7 +148,9 @@ impl Backend for Gbm { /// /// The returned `NativeDisplayType` must be valid for egl and there is no way to test that. pub unsafe trait NativeDisplay { + /// Arguments used to surface creation. type Arguments; + /// Error type thrown by the surface creation in case of failure. type Error: ::std::error::Error + Send + 'static; /// Because one typ might implement multiple `Backend` this function must be called to check /// if the expected `Backend` is used at runtime. diff --git a/src/backend/graphics/egl/surface.rs b/src/backend/graphics/egl/surface.rs index e8f45f8..1a76fc4 100644 --- a/src/backend/graphics/egl/surface.rs +++ b/src/backend/graphics/egl/surface.rs @@ -1,3 +1,5 @@ +//! EGL surface related structs + use super::{EGLContext, SwapBuffersError}; use super::error::*; use super::ffi; diff --git a/src/backend/graphics/egl/wayland.rs b/src/backend/graphics/egl/wayland.rs index 81c0925..952ba64 100644 --- a/src/backend/graphics/egl/wayland.rs +++ b/src/backend/graphics/egl/wayland.rs @@ -1,3 +1,15 @@ +//! Wayland specific EGL functionality - EGL based WlBuffers. +//! +//! The types of this module can be used to initialize hardware acceleration rendering +//! based on EGL for clients as it may enabled usage of `EGLImage` based `WlBuffer`s. +//! +//! To use it bind any backend implementing the `EGLWaylandExtensions` trait, that shall do the +//! rendering (so pick a fast one), to the `wayland_server::Display` of your compositor. +//! Note only one backend may be bould to any `Display` at any time. +//! +//! You may then use the resulting `EGLDisplay` to recieve `EGLImages` of an egl-based `WlBuffer` +//! for rendering. + use backend::graphics::egl::{EGLContext, EglExtensionNotSupportedError, ffi, native}; use backend::graphics::egl::error::*; use backend::graphics::egl::ffi::egl::types::EGLImage; @@ -113,17 +125,26 @@ impl ::std::error::Error for TextureCreationError { } } +/// Texture format types #[repr(i32)] +#[allow(non_camel_case_types)] pub enum Format { + /// RGB format RGB = ffi::egl::TEXTURE_RGB as i32, + /// RGB + alpha channel format RGBA = ffi::egl::TEXTURE_RGBA as i32, + /// External format External = ffi::egl::TEXTURE_EXTERNAL_WL, + /// 2-plane Y and UV format Y_UV = ffi::egl::TEXTURE_Y_UV_WL, + /// 3-plane Y, U and V format Y_U_V = ffi::egl::TEXTURE_Y_U_V_WL, + /// 2-plane Y and XUXV format Y_XUXV = ffi::egl::TEXTURE_Y_XUXV_WL, } impl Format { + /// Amount of planes this format uses pub fn num_planes(&self) -> usize { match *self { Format::RGB | Format::RGBA | Format::External => 1, @@ -133,21 +154,34 @@ impl Format { } } +/// Images of the egl-based `WlBuffer`. pub struct EGLImages { display: Weak, + /// Width in pixels pub width: u32, + /// Height in pixels pub height: u32, + /// If the y-axis is inverted or not pub y_inverted: bool, + /// Format of these images pub format: Format, images: Vec, buffer: WlBuffer, } impl EGLImages { + /// Amount of planes of these `EGLImages` pub fn num_planes(&self) -> usize { self.format.num_planes() } + /// Bind plane to an OpenGL texture id + /// + /// This does only temporarily modify the OpenGL state any changes are reverted before returning. + /// + /// # Unsafety + /// + /// The given `tex_id` needs to be a valid GL texture otherwise undefined behavior might occur. pub unsafe fn bind_to_texture(&self, plane: usize, tex_id: c_uint) -> ::std::result::Result<(), TextureCreationError> { if self.display.upgrade().is_some() { let mut old_tex_id: i32 = 0; @@ -177,6 +211,8 @@ impl Drop for EGLImages { } } +/// Trait any backend type may implement that allows binding a `wayland_server::Display` +/// to create an `EGLDisplay` for egl-based `WlBuffer`s. pub trait EGLWaylandExtensions { /// Binds this EGL context to the given Wayland display. /// @@ -194,6 +230,9 @@ pub trait EGLWaylandExtensions { fn bind_wl_display(&self, display: &Display) -> Result; } +/// Type to recieve `EGLImages` for egl-based `WlBuffer`s. +/// +/// Can be created by using `EGLWaylandExtensions::bind_wl_display`. pub struct EGLDisplay(Weak, *mut wl_display); impl EGLDisplay { @@ -201,6 +240,11 @@ impl EGLDisplay { EGLDisplay(Rc::downgrade(&context.display), display) } + /// Try to recieve `EGLImages` from a given `WlBuffer`. + /// + /// In case the buffer is not managed by egl (but e.g. the wayland::shm module) + /// a `BufferAccessError::NotManaged(WlBuffer)` is returned with the original buffer + /// to render it another way. pub fn egl_buffer_contents(&self, buffer: WlBuffer) -> ::std::result::Result { if let Some(display) = self.0.upgrade() { let mut format: i32 = 0; diff --git a/src/backend/udev.rs b/src/backend/udev.rs index a925b0f..1be67d5 100644 --- a/src/backend/udev.rs +++ b/src/backend/udev.rs @@ -25,6 +25,7 @@ use udev::{Context, Enumerator, Event, EventType, MonitorBuilder, MonitorSocket, use wayland_server::{EventLoopHandle, StateProxy, StateToken}; use wayland_server::sources::{FdEventSource, FdEventSourceImpl, FdInterest}; +/// Udev's `DrmDevice` type based on the underlying session pub struct SessionFdDrmDevice(RawFd); impl AsRawFd for SessionFdDrmDevice {