<NME> mod.rs
<BEF> //! This module represents abstraction on top the linux direct rendering manager api (drm).
//!
//! ## [`DrmDevice`]
//!
//! A device exposes certain properties, which are directly derived
//! from the *device* as perceived by the direct rendering manager api (drm). These resources consists

use std::borrow::Borrow;
use std::error::Error;
use std::os::unix::io::AsRawFd;
use std::path::PathBuf;

//! You can only have so many different pictures, you may display, as you have `crtc`s, but a single image
//! may be put onto multiple displays.
//!
//! An [`encoder`](drm::control::encoder) encodes the data of connected crtcs into a video signal for a fixed set of connectors.
//! E.g. you might have an analog encoder based on a DAG for VGA ports, but another one for digital ones.
//! Also not every encoder might be connected to every crtc.
//!
//! 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 display, 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 have to be explicitly used by the user to be useful.

pub trait DeviceHandler {
    type Device: Device + ?Sized;
    fn vblank(&mut self, surface: &<<Self as DeviceHandler>::Device as Device>::Surface);
    fn error(&mut self, error: <<<Self as DeviceHandler>::Device as Device>::Surface as Surface>::Error);
}

pub trait Device: AsRawFd + DevPath {
    type Surface: Surface;
    type Return: Borrow<Self::Surface>;

    fn set_handler(&mut self, handler: impl DeviceHandler<Device = Self> + 'static);
    fn clear_handler(&mut self);
//! smithay does not make sure that `connectors` are not already in use by another `Surface`. Overlapping `connector`-Sets may
        &mut self,
        ctrc: crtc::Handle,
        mode: Mode,
        connectors: impl Into<<Self::Surface as Surface>::Connectors>,
    ) -> Result<Self::Return, <Self::Surface as Surface>::Error>;
    fn process_events(&mut self);
}

pub trait RawDevice: Device<Surface = <Self as RawDevice>::Surface>
where
    <Self as Device>::Return: Borrow<<Self as RawDevice>::Surface>,
{
    type Surface: RawSurface;
}

//! The state of a `Surface` is double-buffered, meaning all operations that chance the set of `connector`s or their `Mode` are stored and
//! only applied on the next commit. `Surface`s do their best to validate these changes, if possible.
//!
//! A commit/page_flip may be triggered to apply the pending state.
//!
//! ## Rendering
//!
//! The drm infrastructure makes no assumptions about the used renderer and does not interface with them directly.
//! It just provides a way to create framebuffers from various buffer types (mainly `DumbBuffer`s and hardware-backed gbm `BufferObject`s).
//!
//! Buffer management and details about the various types can be found in the [`allocator`-Module](crate::backend::allocator) and
//! rendering abstractions, which can target these buffers can be found in the [`renderer`-Module](crate::backend::renderer).
//!
//! ## [`DrmNode`]
//!
//! A drm node refers to a drm device and the capabilities that may be performed using the node.
//! Generally [`DrmNode`] is primarily used by clients (such as the output backends) which need
//! to allocate buffers for use in X11 or Wayland. If you need to do mode setting, you should use
//! [`DrmDevice`] instead.

pub(crate) mod device;
pub(self) mod error;
pub mod node;

#[cfg(feature = "backend_session")]
pub(self) mod session;
pub(self) mod surface;

pub use device::{DevPath, DrmDevice, DrmEvent, EventMetadata as DrmEventMetadata, Time as DrmEventTime};
pub use error::Error as DrmError;
pub use node::{CreateDrmNodeError, DrmNode, NodeType};
#[cfg(feature = "backend_gbm")]
pub use surface::gbm::{Error as GbmBufferedSurfaceError, GbmBufferedSurface};
pub use surface::DrmSurface;

use drm::control::{crtc, plane, Device as ControlDevice, PlaneType};

/// A set of planes as supported by a crtc
#[derive(Debug)]
pub struct Planes {
    /// The primary plane of the crtc (automatically selected for [DrmDevice::create_surface])
    pub primary: plane::Handle,
    /// The cursor plane of the crtc, if available
    pub cursor: Option<plane::Handle>,
    /// Overlay planes supported by the crtc, if available
    pub overlay: Vec<plane::Handle>,
}

fn planes(
    dev: &impl ControlDevice,
    crtc: &crtc::Handle,
    has_universal_planes: bool,
) -> Result<Planes, DrmError> {
    let mut primary = None;
    let mut cursor = None;
    let mut overlay = Vec::new();

    let planes = dev.plane_handles().map_err(|source| DrmError::Access {
        errmsg: "Error loading plane handles",
        dev: dev.dev_path(),
        source,
    })?;

    let resources = dev.resource_handles().map_err(|source| DrmError::Access {
        errmsg: "Error loading resource handles",
        dev: dev.dev_path(),
        source,
    })?;

    for plane in planes {
        let info = dev.get_plane(plane).map_err(|source| DrmError::Access {
            errmsg: "Failed to get plane information",
            dev: dev.dev_path(),
            source,
        })?;
        let filter = info.possible_crtcs();
        if resources.filter_crtcs(filter).contains(crtc) {
            match plane_type(dev, plane)? {
                PlaneType::Primary => {
                    primary = Some(plane);
                }
                PlaneType::Cursor => {
                    cursor = Some(plane);
                }
                PlaneType::Overlay => {
                    overlay.push(plane);
                }
            };
        }
    }

    Ok(Planes {
        primary: primary.expect("Crtc has no primary plane"),
        cursor: if has_universal_planes { cursor } else { None },
        overlay: if has_universal_planes { overlay } else { Vec::new() },
    })
}

fn plane_type(dev: &impl ControlDevice, plane: plane::Handle) -> Result<PlaneType, DrmError> {
    let props = dev.get_properties(plane).map_err(|source| DrmError::Access {
        errmsg: "Failed to get properties of plane",
        dev: dev.dev_path(),
        source,
    })?;
    let (ids, vals) = props.as_props_and_values();
    for (&id, &val) in ids.iter().zip(vals.iter()) {
        let info = dev.get_property(id).map_err(|source| DrmError::Access {
            errmsg: "Failed to get property info",
            dev: dev.dev_path(),
            source,
        })?;
        if info.name().to_str().map(|x| x == "type").unwrap_or(false) {
            return Ok(match val {
                x if x == (PlaneType::Primary as u64) => PlaneType::Primary,
                x if x == (PlaneType::Cursor as u64) => PlaneType::Cursor,
                _ => PlaneType::Overlay,
            });
        }
    }
    unreachable!()
}

<MSG> drm: Remove associated Return type from Device

<DFF> @@ -7,6 +7,7 @@ use drm::Device as BasicDevice;
 
 use std::borrow::Borrow;
 use std::error::Error;
+use std::iter::IntoIterator;
 use std::os::unix::io::AsRawFd;
 use std::path::PathBuf;
 
@@ -26,13 +27,12 @@ pub mod legacy;
 
 pub trait DeviceHandler {
     type Device: Device + ?Sized;
-    fn vblank(&mut self, surface: &<<Self as DeviceHandler>::Device as Device>::Surface);
+    fn vblank(&mut self, crtc: crtc::Handle);
     fn error(&mut self, error: <<<Self as DeviceHandler>::Device as Device>::Surface as Surface>::Error);
 }
 
 pub trait Device: AsRawFd + DevPath {
     type Surface: Surface;
-    type Return: Borrow<Self::Surface>;
 
     fn set_handler(&mut self, handler: impl DeviceHandler<Device = Self> + 'static);
     fn clear_handler(&mut self);
@@ -40,15 +40,12 @@ pub trait Device: AsRawFd + DevPath {
         &mut self,
         ctrc: crtc::Handle,
         mode: Mode,
-        connectors: impl Into<<Self::Surface as Surface>::Connectors>,
-    ) -> Result<Self::Return, <Self::Surface as Surface>::Error>;
+        connectors: impl IntoIterator<Item = connector::Handle>,
+    ) -> Result<Self::Surface, <Self::Surface as Surface>::Error>;
     fn process_events(&mut self);
 }
 
-pub trait RawDevice: Device<Surface = <Self as RawDevice>::Surface>
-where
-    <Self as Device>::Return: Borrow<<Self as RawDevice>::Surface>,
-{
+pub trait RawDevice: Device<Surface = <Self as RawDevice>::Surface> {
     type Surface: RawSurface;
 }
 

drm: Remove associated Return type from Device