From 945d7128d86db5f7161d8e0d6b57747cf917ae3d Mon Sep 17 00:00:00 2001 From: Victor Brekenfeld Date: Tue, 13 Jul 2021 20:58:04 +0200 Subject: [PATCH] Backend documentation fixes and additions --- src/backend/allocator/swapchain.rs | 2 +- src/backend/drm/device/mod.rs | 2 - src/backend/drm/error.rs | 4 +- src/backend/drm/mod.rs | 8 ++-- src/backend/drm/surface/gbm.rs | 19 ++------ src/backend/drm/surface/mod.rs | 4 +- src/backend/egl/context.rs | 14 +++--- src/backend/egl/display.rs | 4 +- src/backend/egl/error.rs | 11 +++-- src/backend/egl/ffi.rs | 3 ++ src/backend/egl/mod.rs | 73 +++++++++--------------------- src/backend/egl/native.rs | 1 - src/backend/egl/surface.rs | 4 +- src/backend/renderer/gles2/mod.rs | 2 +- 14 files changed, 57 insertions(+), 94 deletions(-) diff --git a/src/backend/allocator/swapchain.rs b/src/backend/allocator/swapchain.rs index e5b1339..67f4a2d 100644 --- a/src/backend/allocator/swapchain.rs +++ b/src/backend/allocator/swapchain.rs @@ -99,7 +99,7 @@ where B: Buffer, U: 'static, { - /// Create a new swapchain with the desired allocator and dimensions and pixel format for the created buffers. + /// Create a new swapchain with the desired allocator, dimensions and pixel format for the created buffers. pub fn new( allocator: A, width: u32, diff --git a/src/backend/drm/device/mod.rs b/src/backend/drm/device/mod.rs index 1ba3348..c12931e 100644 --- a/src/backend/drm/device/mod.rs +++ b/src/backend/drm/device/mod.rs @@ -213,8 +213,6 @@ impl DrmDevice { /// - [`crtcs`](drm::control::crtc) represent scanout engines of the device pointing to one framebuffer. \ /// Their responsibility is to read the data of the framebuffer and export it into an "Encoder". \ /// The number of crtc's represent the number of independant output devices the hardware may handle. - /// - [`planes`](drm::control::plane) represent a single plane on a crtc, which is composite together with - /// other planes on the same crtc to present the final image. /// - [`mode`](drm::control::Mode) describes the resolution and rate of images produced by the crtc and \ /// has to be compatible with the provided `connectors`. /// - [`connectors`](drm::control::connector) - List of connectors driven by the crtc. At least one(!) connector needs to be \ diff --git a/src/backend/drm/error.rs b/src/backend/drm/error.rs index 7abb780..3458da9 100644 --- a/src/backend/drm/error.rs +++ b/src/backend/drm/error.rs @@ -28,8 +28,8 @@ pub enum Error { /// Mode is not compatible with all given connectors #[error("Mode `{0:?}` is not compatible with all given connectors")] ModeNotSuitable(Mode), - /// The given crtc is already in use by another backend - #[error("Crtc `{0:?}` is already in use by another backend")] + /// The given crtc is already in use by another surface + #[error("Crtc `{0:?}` is already in use by another surface")] CrtcAlreadyInUse(crtc::Handle), /// This operation would result in a surface without connectors. #[error("Surface of crtc `{0:?}` would have no connectors, which is not accepted")] diff --git a/src/backend/drm/mod.rs b/src/backend/drm/mod.rs index 37d79ea..2759b83 100644 --- a/src/backend/drm/mod.rs +++ b/src/backend/drm/mod.rs @@ -2,7 +2,7 @@ //! //! ## DrmDevice //! -//! A device exposes certain properties, which are directly derived +//! A device exposes certain properties, which are directly derived //! from the *device* as perceived by the direct rendering manager api (drm). These resources consists //! out of connectors, encoders, framebuffers, planes and crtcs. //! @@ -20,13 +20,13 @@ //! //! A [`connector`](drm::control::connector) represents a port on your computer, possibly with a connected monitor, TV, capture card, etc. //! -//! A [`framebuffer`](drm::control::framebuffer) represents a buffer you may be rendering to, see `Surface` below. +//! A [`framebuffer`](drm::control::framebuffer) represents a buffer you may be rendering to, see `DrmSurface` below. //! //! A [`plane`](drm::control::plane) adds another layer on top of the crtcs, which allow us to layer multiple images on top of each other more efficiently -//! then by combining the rendered images in the rendering phase, e.g. via OpenGL. Planes can be explicitly used by the user. +//! then by combining the rendered images in the rendering phase, e.g. via OpenGL. Planes have to be explicitly used by the user to be useful. //! Every device has at least one primary plane used to display an image to the whole crtc. Additionally cursor and overlay planes may be present. //! Cursor planes are usually very restricted in size and meant to be used for hardware cursors, while overlay planes may -//! be used for performance reasons to display any overlay on top of the image, e.g. top-most windows. +//! be used for performance reasons to display any overlay on top of the image, e.g. the top-most windows. //! //! The main functionality of a `Device` in smithay is to give access to all these properties for the user to //! choose an appropriate rendering configuration. What that means is defined by the requirements and constraints documented diff --git a/src/backend/drm/surface/gbm.rs b/src/backend/drm/surface/gbm.rs index 30ed390..6c2e48f 100644 --- a/src/backend/drm/surface/gbm.rs +++ b/src/backend/drm/surface/gbm.rs @@ -16,13 +16,7 @@ use crate::backend::SwapBuffersError; use slog::{debug, error, o, trace, warn}; -/// Simplified by limited abstraction to link single [`DrmSurface`]s to renderers. -/// -/// # Use-case -/// -/// In some scenarios it might be enough to use of a drm-surface as the one and only target -/// of a single renderer. In these cases `DrmRenderSurface` provides a way to quickly -/// get up and running without manually handling and binding buffers. +/// Simplified abstraction of a swapchain for gbm-buffers displayed on a [`DrmSurface`]. pub struct GbmBufferedSurface { buffers: Buffers, swapchain: Swapchain, BufferObject<()>, (Dmabuf, FbHandle)>, @@ -43,15 +37,12 @@ impl GbmBufferedSurface where D: AsRawFd + 'static, { - /// Create a new `DrmRendererSurface` from a given compatible combination - /// of a surface, an allocator and a renderer. + /// Create a new `GbmBufferedSurface` from a given compatible combination + /// of a surface, an allocator and renderer formats. /// /// To sucessfully call this function, you need to have a renderer, - /// which can render into a Dmabuf, and an allocator, which can create - /// a buffer type, which can be converted into a Dmabuf. - /// - /// The function will futhermore check for compatibility by enumerating - /// supported pixel formats and choosing an appropriate one. + /// which can render into a Dmabuf, and a gbm allocator that can produce + /// buffers of a supported format for rendering. #[allow(clippy::type_complexity)] pub fn new( drm: DrmSurface, diff --git a/src/backend/drm/surface/mod.rs b/src/backend/drm/surface/mod.rs index 0282e6d..459fae7 100644 --- a/src/backend/drm/surface/mod.rs +++ b/src/backend/drm/surface/mod.rs @@ -63,7 +63,7 @@ impl DrmSurface { self.primary } - /// Currently used [`connector`](drm::control::connector)s of this `Surface` + /// Currently used [`connector`](drm::control::connector)s of this surface pub fn current_connectors(&self) -> impl IntoIterator { match &*self.internal { DrmSurfaceInternal::Atomic(surf) => surf.current_connectors(), @@ -72,7 +72,7 @@ impl DrmSurface { } /// Returns the pending [`connector`](drm::control::connector)s - /// used after the next [`commit`](DrmSurface::commit) of this [`DrmSurface`] + /// used after the next [`commit`](DrmSurface::commit) of this surface pub fn pending_connectors(&self) -> impl IntoIterator { match &*self.internal { DrmSurfaceInternal::Atomic(surf) => surf.pending_connectors(), diff --git a/src/backend/egl/context.rs b/src/backend/egl/context.rs index 92a28c2..1ee15a5 100644 --- a/src/backend/egl/context.rs +++ b/src/backend/egl/context.rs @@ -171,7 +171,7 @@ impl EGLContext { /// # Safety /// /// This function is marked unsafe, because the context cannot be made current - /// on multiple threads. + /// on multiple threads without being unbound again (see `unbind`). pub unsafe fn make_current_with_surface(&self, surface: &EGLSurface) -> Result<(), MakeCurrentError> { let surface_ptr = surface.surface.load(Ordering::SeqCst); wrap_egl_call(|| { @@ -186,7 +186,7 @@ impl EGLContext { /// # Safety /// /// This function is marked unsafe, because the context cannot be made current - /// on multiple threads without being unbound again (see `unbind`) + /// on multiple threads without being unbound again (see `unbind`). pub unsafe fn make_current(&self) -> Result<(), MakeCurrentError> { wrap_egl_call(|| { ffi::egl::MakeCurrent( @@ -217,7 +217,7 @@ impl EGLContext { /// Unbinds this context from the current thread, if set. /// - /// This does nothing if this context is not the current context + /// This does nothing if this context is not the current context. pub fn unbind(&self) -> Result<(), MakeCurrentError> { if self.is_current() { wrap_egl_call(|| unsafe { @@ -232,12 +232,12 @@ impl EGLContext { Ok(()) } - /// Returns a list of formats for dmabufs that can be rendered to + /// Returns a list of formats for dmabufs that can be rendered to. pub fn dmabuf_render_formats(&self) -> &HashSet { &self.display.dmabuf_render_formats } - /// Returns a list of formats for dmabufs that can be used as textures + /// Returns a list of formats for dmabufs that can be used as textures. pub fn dmabuf_texture_formats(&self) -> &HashSet { &self.display.dmabuf_import_formats } @@ -262,7 +262,7 @@ pub struct GlAttributes { /// `(3, 0)` will request a OpenGL ES 3.0 context for example. /// `(2, 0)` is the minimum. pub version: (u8, u8), - /// OpenGL profile to use + /// OpenGL profile to use. pub profile: Option, /// Whether to enable the debug flag of the context. /// @@ -276,7 +276,7 @@ pub struct GlAttributes { /// Describes the requested OpenGL context profiles. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum GlProfile { - /// Include all the immediate more functions and definitions. + /// Include all the immediate functions and definitions. Compatibility, /// Include all the future-compatible functions and definitions. Core, diff --git a/src/backend/egl/display.rs b/src/backend/egl/display.rs index 98542a8..c1654c4 100644 --- a/src/backend/egl/display.rs +++ b/src/backend/egl/display.rs @@ -389,7 +389,7 @@ impl EGLDisplay { Ok((desc, config_id)) } - /// Get a handle to the underlying native EGLDisplay + /// Get a handle to the underlying raw EGLDisplay handle pub fn get_display_handle(&self) -> Arc { self.display.clone() } @@ -404,7 +404,7 @@ impl EGLDisplay { self.extensions.clone() } - /// Imports a dmabuf as an eglimage + /// Imports a [`Dmabuf`] as an [`EGLImage`] pub fn create_image_from_dmabuf(&self, dmabuf: &Dmabuf) -> Result { if !self.extensions.iter().any(|s| s == "EGL_KHR_image_base") && !self diff --git a/src/backend/egl/error.rs b/src/backend/egl/error.rs index 5ff1843..d389182 100644 --- a/src/backend/egl/error.rs +++ b/src/backend/egl/error.rs @@ -39,11 +39,11 @@ pub enum Error { /// No EGLDisplay is currently bound to this `WlDisplay` #[error("No EGLDisplay is currently bound to this `WlDisplay`")] NoEGLDisplayBound, - /// Index of plane is out of bounds for `EGLImages` - #[error("Index of plane is out of bounds for `EGLImages`")] + /// Index of plane is out of bounds for `EGLBuffer` + #[error("Index of plane is out of bounds for `EGLBuffer`")] PlaneIndexOutOfBounds, - /// Failed to create `EGLImages` from the buffer - #[error("Failed to create `EGLImages` from the buffer")] + /// Failed to create `EGLBuffer` from the buffer + #[error("Failed to create `EGLBuffer` from the buffer")] EGLImageCreationFailed, } @@ -135,7 +135,8 @@ impl EGLError { } } -pub(crate) fn wrap_egl_call R>(call: F) -> Result { +/// Wraps a raw egl call and returns error codes from `eglGetError`, if it fails. +pub fn wrap_egl_call R>(call: F) -> Result { let res = call(); EGLError::from_last_call().map(|()| res) } diff --git a/src/backend/egl/ffi.rs b/src/backend/egl/ffi.rs index e40867c..0f4599e 100644 --- a/src/backend/egl/ffi.rs +++ b/src/backend/egl/ffi.rs @@ -41,6 +41,8 @@ extern "system" fn egl_debug_log( }); } +/// Loads libEGL symbols, if not loaded already. +/// This normally happens automatically during [`EGLDisplay`] initialization. pub fn make_sure_egl_is_loaded() -> Result, Error> { use std::{ ffi::{CStr, CString}, @@ -107,6 +109,7 @@ pub fn make_sure_egl_is_loaded() -> Result, Error> { Ok(extensions) } +/// Module containing raw egl function bindings #[allow(clippy::all, missing_debug_implementations)] pub mod egl { use super::*; diff --git a/src/backend/egl/mod.rs b/src/backend/egl/mod.rs index 746cc67..0075b6b 100644 --- a/src/backend/egl/mod.rs +++ b/src/backend/egl/mod.rs @@ -1,30 +1,30 @@ //! Common traits and types for egl rendering //! -//! Large parts of this module are taken from -//! [glutin src/api/egl](https://github.com/tomaka/glutin/tree/044e651edf67a2029eecc650dd42546af1501414/src/api/egl/) +//! This module has multiple responsibilities related to functionality provided by libEGL: +//! Initializing EGL objects to: +//! - initialize usage of EGL based [`WlBuffer`](wayland_server::protocol::wl_buffer::WlBuffer)s via `wl_drm`. +//! - initialize OpenGL contexts from. +//! - Import/Export external resources to/from OpenGL //! -//! It therefore falls under -//! [glutin's Apache 2.0 license](https://github.com/tomaka/glutin/tree/044e651edf67a2029eecc650dd42546af1501414/LICENSE) +//! To use this module, you first need to create a [`EGLDisplay`] through a supported EGL platform +//! as inidicated by an implementation of the `native::EGLNativeDisplay` trait. //! -//! Wayland specific EGL functionality - EGL based [`WlBuffer`](wayland_server::protocol::wl_buffer::WlBuffer)s. +//! You may bind the [`EGLDisplay`], that shall be used by clients for rendering (so pick one initialized by a fast platform) +//! to the [`wayland_server::Display`] of your compositor. Note only one backend may be bound to any [`Display`](wayland_server::Display) at any time. //! -//! 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`](wayland_server::protocol::wl_buffer::WlBuffer)s. -//! -//! To use it bind the [`EGLDisplay`] 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 bound to any [`Display`](wayland_server::Display) at any time. -//! -//! You may then use the resulting [`EGLDisplay`] to receive [`EGLBuffer`] +//! You may then use the resulting [`display::EGLBufferReader`] to receive [`EGLBuffer`] //! of an EGL-based [`WlBuffer`](wayland_server::protocol::wl_buffer::WlBuffer) for rendering. +//! Renderers implementing the [`ImportEGL`](crate::backend::renderer::ImportEGL)-trait can manage the buffer reader for you. +//! +//! To create OpenGL contexts you may create [`EGLContext`]s from the display and if the context is initialized with a config +//! it may also be used to initialize an [`EGLSurface`], which can be [bound](crate::backend::renderer::Bind) to some renderers. +//! +//! Alternatively you may import [`dmabuf`](crate::backend::allocator::dmabuf)s using the display, which result +//! in an [`EGLImage`], which can be rendered into by OpenGL. This is perferrable to using surfaces as the dmabuf can be +//! passed around freely making resource-management and more complex use-cases like Multi-GPU rendering easier to manage. +//! Renderers based on EGL may support doing this for you by allowing you to [`Bind`](crate::backend::renderer::Bind) a dmabuf directly. +//! -/* -#[cfg(feature = "renderer_gl")] -use crate::backend::graphics::{ - gl::{ffi as gl_ffi, GLGraphicsBackend}, - SwapBuffersError as GraphicsSwapBuffersError, -}; -*/ use std::fmt; pub mod context; @@ -92,7 +92,7 @@ pub enum BufferAccessError { /// This buffer is not managed by the EGL buffer #[error("This buffer is not managed by EGL. Err: {0:}")] NotManaged(#[source] EGLError), - /// Failed to create `EGLImages` from the buffer + /// Failed to create `EGLBuffer` from the buffer #[error("Failed to create EGLImages from the buffer. Err: {0:}")] EGLImageCreationFailed(#[source] EGLError), /// The required EGL extension is not supported by the underlying EGL implementation @@ -186,35 +186,6 @@ impl From for GraphicsSwapBuffersError { } } -/// Error that might happen when binding an `EGLImage` to a GL texture -#[derive(Debug, Clone, PartialEq, thiserror::Error)] -pub enum TextureCreationError { - /// The given plane index is out of bounds - #[error("This buffer is not managed by EGL")] - PlaneIndexOutOfBounds, - /// The OpenGL context has been lost and needs to be recreated. - /// - /// All the objects associated to it (textures, buffers, programs, etc.) - /// need to be recreated from scratch. - /// - /// Operations will have no effect. Functions that read textures, buffers, etc. - /// from OpenGL will return uninitialized data instead. - /// - /// A context loss usually happens on mobile devices when the user puts the - /// application on sleep and wakes it up later. However any OpenGL implementation - /// can theoretically lose the context at any time. - #[error("The context has been lost, it needs to be recreated")] - ContextLost, - /// Required OpenGL Extension for texture creation is missing - #[error("Required OpenGL Extension for texture creation is missing: {0}")] - GLExtensionNotSupported(&'static str), - /// Failed to bind the `EGLImage` to the given texture - /// - /// The given argument is the GL error code - #[error("Failed to create EGLImages from the buffer (GL error code {0:x}")] - TextureBindingFailed(u32), -} - /// Texture format types #[repr(i32)] #[allow(non_camel_case_types)] @@ -261,7 +232,7 @@ pub struct EGLBuffer { #[cfg(feature = "wayland_frontend")] impl EGLBuffer { - /// Amount of planes of these `EGLImages` + /// Amount of planes of this EGLBuffer pub fn num_planes(&self) -> usize { self.format.num_planes() } diff --git a/src/backend/egl/native.rs b/src/backend/egl/native.rs index fcb1e97..cae3a3e 100644 --- a/src/backend/egl/native.rs +++ b/src/backend/egl/native.rs @@ -172,7 +172,6 @@ impl EGLNativeDisplay for WinitWindow { /// The returned [`NativeWindowType`](ffi::NativeWindowType) must be valid for EGL /// and there is no way to test that. pub unsafe trait EGLNativeSurface: Send + Sync { - /// Error type thrown by the surface creation in case of failure. /// Create an EGLSurface from the internal native type. /// /// Must be able to deal with re-creation of existing resources, diff --git a/src/backend/egl/surface.rs b/src/backend/egl/surface.rs index bbb4d24..0070ff4 100644 --- a/src/backend/egl/surface.rs +++ b/src/backend/egl/surface.rs @@ -46,10 +46,10 @@ impl EGLSurface { /// Create a new `EGLSurface`. /// /// Requires: - /// - A EGLDisplay supported by the corresponding plattform matching the surface type + /// - A EGLDisplay supported by the corresponding platform matching the surface type /// - A pixel format - /// - An (optional) preference for double_buffering /// - A valid `EGLConfig` (see `EGLContext::config_id()`) + /// - A native type backing the surface matching the used platform /// - An (optional) Logger pub fn new( display: &EGLDisplay, diff --git a/src/backend/renderer/gles2/mod.rs b/src/backend/renderer/gles2/mod.rs index 9724b28..cc78b94 100644 --- a/src/backend/renderer/gles2/mod.rs +++ b/src/backend/renderer/gles2/mod.rs @@ -407,7 +407,7 @@ impl Gles2Renderer { /// # Implementation details /// /// - Texture handles created by the resulting renderer are valid for every rendered created with an - /// `EGLContext` shared with the given one (see `EGLContext::new_shared`) and can be used and destroyed on + /// `EGLContext` shared with the given one (see `EGLContext::new_shared`) and can be used on /// any of these renderers. /// - This renderer has no default framebuffer, use `Bind::bind` before rendering. /// - Binding a new target, while another one is already bound, will replace the current target.