Backend documentation fixes and additions

This commit is contained in:
Victor Brekenfeld 2021-07-13 20:58:04 +02:00
parent af2aa017bf
commit 945d7128d8
14 changed files with 57 additions and 94 deletions

View File

@ -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,

View File

@ -213,8 +213,6 @@ impl<A: AsRawFd + 'static> DrmDevice<A> {
/// - [`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 \

View File

@ -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")]

View File

@ -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

View File

@ -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<D: AsRawFd + 'static> {
buffers: Buffers<D>,
swapchain: Swapchain<GbmDevice<D>, BufferObject<()>, (Dmabuf, FbHandle<D>)>,
@ -43,15 +37,12 @@ impl<D> GbmBufferedSurface<D>
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<L>(
drm: DrmSurface<D>,

View File

@ -63,7 +63,7 @@ impl<A: AsRawFd + 'static> DrmSurface<A> {
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<Item = connector::Handle> {
match &*self.internal {
DrmSurfaceInternal::Atomic(surf) => surf.current_connectors(),
@ -72,7 +72,7 @@ impl<A: AsRawFd + 'static> DrmSurface<A> {
}
/// 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<Item = connector::Handle> {
match &*self.internal {
DrmSurfaceInternal::Atomic(surf) => surf.pending_connectors(),

View File

@ -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<DrmFormat> {
&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<DrmFormat> {
&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<GlProfile>,
/// 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,

View File

@ -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<EGLDisplayHandle> {
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<EGLImage, Error> {
if !self.extensions.iter().any(|s| s == "EGL_KHR_image_base")
&& !self

View File

@ -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, F: FnOnce() -> R>(call: F) -> Result<R, EGLError> {
/// Wraps a raw egl call and returns error codes from `eglGetError`, if it fails.
pub fn wrap_egl_call<R, F: FnOnce() -> R>(call: F) -> Result<R, EGLError> {
let res = call();
EGLError::from_last_call().map(|()| res)
}

View File

@ -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<Vec<String>, Error> {
use std::{
ffi::{CStr, CString},
@ -107,6 +109,7 @@ pub fn make_sure_egl_is_loaded() -> Result<Vec<String>, Error> {
Ok(extensions)
}
/// Module containing raw egl function bindings
#[allow(clippy::all, missing_debug_implementations)]
pub mod egl {
use super::*;

View File

@ -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<MakeCurrentError> 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()
}

View File

@ -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,

View File

@ -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<N, L>(
display: &EGLDisplay,

View File

@ -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.