fallback: support FallbackDevice<GbmDevice, EglStreamDevice> for automatic nvidia support

This commit is contained in:
Victor Brekenfeld 2020-05-22 23:14:49 +02:00
parent 53f5753943
commit 9acd109a04
2 changed files with 280 additions and 65 deletions

View File

@ -2,9 +2,20 @@
//! Types to make fallback device initialization easier
//!
#[cfg(feature = "backend_drm_egl")]
use crate::backend::drm::egl::{Arguments as EglDeviceArguments, EglDevice, Error as EglDeviceError};
#[cfg(all(feature = "backend_drm_atomic", feature = "backend_drm_legacy"))]
use crate::backend::drm::{atomic::AtomicDrmDevice, legacy::LegacyDrmDevice};
use crate::backend::drm::{common::Error, Device, DeviceHandler, RawDevice, RawSurface, Surface};
#[cfg(all(feature = "backend_drm_gbm", feature = "backend_drm_eglstream"))]
use crate::backend::drm::{
eglstream::{EglStreamDevice, Error as EglStreamError},
gbm::{Error as GbmError, GbmDevice},
};
#[cfg(feature = "backend_drm_egl")]
use crate::backend::egl::context::{GlAttributes, PixelFormatRequirements};
#[cfg(feature = "backend_drm_egl")]
use crate::backend::egl::native::{Backend, NativeDisplay, NativeSurface};
use crate::backend::egl::Error as EGLError;
#[cfg(feature = "use_system_lib")]
use crate::backend::egl::{display::EGLBufferReader, EGLGraphicsBackend};
@ -36,23 +47,25 @@ pub enum FallbackDevice<D1: Device + 'static, D2: Device + 'static> {
Fallback(D2),
}
struct FallbackDeviceHandlerD1<E, C, S1, S2, D1, D2>(
struct FallbackDeviceHandlerD1<E1, E2, C, S1, S2, D1, D2>(
Box<dyn DeviceHandler<Device = FallbackDevice<D1, D2>> + 'static>,
)
where
E: std::error::Error + Send + 'static,
E1: std::error::Error + Send + 'static,
E2: std::error::Error + Send + 'static,
C: IntoIterator<Item = connector::Handle> + 'static,
S1: Surface<Error = E, Connectors = C> + 'static,
S2: Surface<Error = E, Connectors = C> + 'static,
S1: Surface<Error = E1, Connectors = C> + 'static,
S2: Surface<Error = E2, Connectors = C> + 'static,
D1: Device<Surface = S1> + 'static,
D2: Device<Surface = S2> + 'static;
impl<E, C, S1, S2, D1, D2> DeviceHandler for FallbackDeviceHandlerD1<E, C, S1, S2, D1, D2>
impl<E1, E2, C, S1, S2, D1, D2> DeviceHandler for FallbackDeviceHandlerD1<E1, E2, C, S1, S2, D1, D2>
where
E: std::error::Error + Send + 'static,
E1: std::error::Error + Send + 'static,
E2: std::error::Error + Send + 'static,
C: IntoIterator<Item = connector::Handle> + 'static,
S1: Surface<Error = E, Connectors = C> + 'static,
S2: Surface<Error = E, Connectors = C> + 'static,
S1: Surface<Error = E1, Connectors = C> + 'static,
S2: Surface<Error = E2, Connectors = C> + 'static,
D1: Device<Surface = S1> + 'static,
D2: Device<Surface = S2> + 'static,
{
@ -61,28 +74,30 @@ where
fn vblank(&mut self, crtc: crtc::Handle) {
self.0.vblank(crtc)
}
fn error(&mut self, error: E) {
self.0.error(error);
fn error(&mut self, error: E1) {
self.0.error(EitherError::Either(error));
}
}
struct FallbackDeviceHandlerD2<E, C, S1, S2, D1, D2>(
struct FallbackDeviceHandlerD2<E1, E2, C, S1, S2, D1, D2>(
Box<dyn DeviceHandler<Device = FallbackDevice<D1, D2>> + 'static>,
)
where
E: std::error::Error + Send + 'static,
E1: std::error::Error + Send + 'static,
E2: std::error::Error + Send + 'static,
C: IntoIterator<Item = connector::Handle> + 'static,
S1: Surface<Error = E, Connectors = C> + 'static,
S2: Surface<Error = E, Connectors = C> + 'static,
S1: Surface<Error = E1, Connectors = C> + 'static,
S2: Surface<Error = E2, Connectors = C> + 'static,
D1: Device<Surface = S1> + 'static,
D2: Device<Surface = S2> + 'static;
impl<E, C, S1, S2, D1, D2> DeviceHandler for FallbackDeviceHandlerD2<E, C, S1, S2, D1, D2>
impl<E1, E2, C, S1, S2, D1, D2> DeviceHandler for FallbackDeviceHandlerD2<E1, E2, C, S1, S2, D1, D2>
where
E: std::error::Error + Send + 'static,
E1: std::error::Error + Send + 'static,
E2: std::error::Error + Send + 'static,
C: IntoIterator<Item = connector::Handle> + 'static,
S1: Surface<Error = E, Connectors = C> + 'static,
S2: Surface<Error = E, Connectors = C> + 'static,
S1: Surface<Error = E1, Connectors = C> + 'static,
S2: Surface<Error = E2, Connectors = C> + 'static,
D1: Device<Surface = S1> + 'static,
D2: Device<Surface = S2> + 'static,
{
@ -91,8 +106,8 @@ where
fn vblank(&mut self, crtc: crtc::Handle) {
self.0.vblank(crtc)
}
fn error(&mut self, error: E) {
self.0.error(error);
fn error(&mut self, error: E2) {
self.0.error(EitherError::Or(error));
}
}
@ -147,9 +162,33 @@ pub enum FallbackSurface<S1: Surface, S2: Surface> {
Fallback(S2),
}
/// Enum uniting two kinds of possible errors.
#[derive(Debug, thiserror::Error)]
pub enum EitherError<E1: std::error::Error + 'static, E2: std::error::Error + 'static> {
/// Either this error
#[error("{0}")]
Either(#[source] E1),
/// Or this error
#[error("{0}")]
Or(#[source] E2),
}
impl<E1, E2> Into<SwapBuffersError> for EitherError<E1, E2>
where
E1: std::error::Error + Into<SwapBuffersError> + 'static,
E2: std::error::Error + Into<SwapBuffersError> + 'static,
{
fn into(self) -> SwapBuffersError {
match self {
EitherError::Either(err) => err.into(),
EitherError::Or(err) => err.into(),
}
}
}
#[cfg(all(feature = "backend_drm_atomic", feature = "backend_drm_legacy"))]
impl<A: AsRawFd + Clone + 'static> FallbackDevice<AtomicDrmDevice<A>, LegacyDrmDevice<A>> {
/// Try to initialize an [`AtomicDrmDevice`](::backend::drm:;atomic::AtomicDrmDevice)
/// Try to initialize an [`AtomicDrmDevice`](::backend::drm::atomic::AtomicDrmDevice)
/// and fall back to a [`LegacyDrmDevice`] if atomic-modesetting is not supported.
///
/// # Arguments
@ -203,6 +242,146 @@ impl<A: AsRawFd + Clone + 'static> FallbackDevice<AtomicDrmDevice<A>, LegacyDrmD
}
}
#[cfg(all(
feature = "backend_drm_gbm",
feature = "backend_drm_eglstream",
feature = "backend_udev"
))]
type GbmOrEglStreamError<D> = EitherError<
GbmError<<<D as Device>::Surface as Surface>::Error>,
EglStreamError<<<D as Device>::Surface as Surface>::Error>,
>;
#[cfg(all(
feature = "backend_drm_gbm",
feature = "backend_drm_eglstream",
feature = "backend_udev"
))]
impl<D> FallbackDevice<GbmDevice<D>, EglStreamDevice<D>>
where
D: RawDevice + ControlDevice + 'static,
{
/// Try to initialize a [`GbmDevice`](::backend::drm::gbm::GbmDevice)
/// or a [`EglStreamDevice`](::backend::drm::eglstream::EglStreamDevice) depending on the used driver.
///
/// # Arguments
///
/// - `dev` - Open drm device (needs implement [`RawDevice`](::backend::drm::RawDevice))
/// - `logger` - Optional [`slog::Logger`] to be used by the resulting device.
///
/// # Return
///
/// Returns an error, if the choosen device fails to initialize.
pub fn new<L>(dev: D, logger: L) -> Result<Self, GbmOrEglStreamError<D>>
where
L: Into<Option<::slog::Logger>>,
{
let log = crate::slog_or_stdlog(logger).new(o!("smithay_module" => "backend_drm_fallback"));
let driver = crate::backend::udev::driver(dev.device_id()).expect("Failed to query device");
info!(log, "Drm device driver: {:?}", driver);
if driver.as_ref().and_then(|x| x.to_str()) == Some("nvidia") {
Ok(FallbackDevice::Fallback(
EglStreamDevice::new(dev, log).map_err(EitherError::Or)?,
))
} else {
Ok(FallbackDevice::Preference(
GbmDevice::new(dev, log.clone()).map_err(EitherError::Either)?,
))
}
}
}
#[cfg(feature = "backend_drm_egl")]
type EglUnderlying<D1, D2> = EitherError<
EglDeviceError<<<D1 as Device>::Surface as Surface>::Error>,
EglDeviceError<<<D2 as Device>::Surface as Surface>::Error>,
>;
#[cfg(feature = "backend_drm_egl")]
type FallbackEglDevice<B1, D1, B2, D2> = FallbackDevice<EglDevice<B1, D1>, EglDevice<B2, D2>>;
#[cfg(feature = "backend_drm_egl")]
impl<D1, D2> FallbackDevice<D1, D2>
where
D1: Device + 'static,
<D1 as Device>::Surface: NativeSurface<Error = <<D1 as Device>::Surface as Surface>::Error>,
D2: Device + 'static,
<D2 as Device>::Surface: NativeSurface<Error = <<D2 as Device>::Surface as Surface>::Error>,
{
/// Try to create a new [`EglDevice`] from a [`FallbackDevice`] containing two compatible device types.
///
/// This helper function is necessary as implementing [`NativeDevice`](::backend::egl::native::NativeDevice) for [`FallbackDevice`] is impossible
/// as selecting the appropriate [`Backend`](::backend::egl::native::Backend) would be impossible without knowing
/// the underlying device type, that was selected by [`FallbackDevice`].
///
/// Returns an error if the context creation was not successful.
pub fn new_egl<B1, B2, L>(
dev: FallbackDevice<D1, D2>,
logger: L,
) -> Result<FallbackEglDevice<B1, D1, B2, D2>, EglUnderlying<D1, D2>>
where
B1: Backend<Surface = <D1 as Device>::Surface, Error = <<D1 as Device>::Surface as Surface>::Error>
+ 'static,
D1: NativeDisplay<B1, Arguments = EglDeviceArguments>,
B2: Backend<Surface = <D2 as Device>::Surface, Error = <<D2 as Device>::Surface as Surface>::Error>
+ 'static,
D2: NativeDisplay<B2, Arguments = EglDeviceArguments>,
L: Into<Option<::slog::Logger>>,
{
let log = crate::slog_or_stdlog(logger).new(o!("smithay_module" => "backend_drm_fallback"));
match dev {
FallbackDevice::Preference(gbm) => match EglDevice::new(gbm, log) {
Ok(dev) => Ok(FallbackDevice::Preference(dev)),
Err(err) => Err(EglUnderlying::<D1, D2>::Either(err)),
},
FallbackDevice::Fallback(eglstream) => match EglDevice::new(eglstream, log) {
Ok(dev) => Ok(FallbackDevice::Fallback(dev)),
Err(err) => Err(EglUnderlying::<D1, D2>::Or(err)),
},
}
}
/// Try to create a new [`EglDevice`] from a [`FallbackDevice`] containing two compatible device types with
/// the given attributes and requirements as defaults for new surfaces.
///
/// This helper function is necessary as implementing [`NativeDevice`](::backend::egl::native::NativeDevice) for [`FallbackDevice`] is impossible
/// as selecting the appropriate [`Backend`](::backend::egl::native::Backend) would be impossible without knowing
/// the underlying device type, that was selected by [`FallbackDevice`].
///
/// Returns an error if the context creation was not successful.
pub fn new_egl_with_defaults<B1, B2, L>(
dev: FallbackDevice<D1, D2>,
default_attributes: GlAttributes,
default_requirements: PixelFormatRequirements,
logger: L,
) -> Result<FallbackEglDevice<B1, D1, B2, D2>, EglUnderlying<D1, D2>>
where
B1: Backend<Surface = <D1 as Device>::Surface, Error = <<D1 as Device>::Surface as Surface>::Error>
+ 'static,
D1: NativeDisplay<B1, Arguments = EglDeviceArguments>,
B2: Backend<Surface = <D2 as Device>::Surface, Error = <<D2 as Device>::Surface as Surface>::Error>
+ 'static,
D2: NativeDisplay<B2, Arguments = EglDeviceArguments>,
L: Into<Option<::slog::Logger>>,
{
let log = crate::slog_or_stdlog(logger).new(o!("smithay_module" => "backend_drm_fallback"));
match dev {
FallbackDevice::Preference(gbm) => {
match EglDevice::new_with_defaults(gbm, default_attributes, default_requirements, log) {
Ok(dev) => Ok(FallbackDevice::Preference(dev)),
Err(err) => Err(EglUnderlying::<D1, D2>::Either(err)),
}
}
FallbackDevice::Fallback(eglstream) => {
match EglDevice::new_with_defaults(eglstream, default_attributes, default_requirements, log) {
Ok(dev) => Ok(FallbackDevice::Fallback(dev)),
Err(err) => Err(EglUnderlying::<D1, D2>::Or(err)),
}
}
}
}
}
macro_rules! fallback_device_impl {
($func_name:ident, $self:ty, $return:ty, $($arg_name:ident : $arg_ty:ty),*) => {
fn $func_name(self: $self, $($arg_name : $arg_ty),*) -> $return {
@ -219,6 +398,19 @@ macro_rules! fallback_device_impl {
fallback_device_impl!($func_name, $self, ());
};
}
macro_rules! fallback_device_err_impl {
($func_name:ident, $self:ty, $return:ty, $($arg_name:ident : $arg_ty:ty),*) => {
fn $func_name(self: $self, $($arg_name : $arg_ty),*) -> $return {
match self {
FallbackDevice::Preference(dev) => dev.$func_name($($arg_name),*).map_err(EitherError::Either),
FallbackDevice::Fallback(dev) => dev.$func_name($($arg_name),*).map_err(EitherError::Or),
}
}
};
($func_name:ident, $self:ty, $return:ty) => {
fallback_device_err_impl!($func_name, $self, $return,);
};
}
macro_rules! fallback_surface_impl {
($func_name:ident, $self:ty, $return:ty, $($arg_name:ident : $arg_ty:ty),*) => {
@ -236,6 +428,16 @@ macro_rules! fallback_surface_impl {
fallback_surface_impl!($func_name, $self, ());
};
}
macro_rules! fallback_surface_err_impl {
($func_name:ident, $self:ty, $return:ty, $($arg_name:ident : $arg_ty:ty),*) => {
fn $func_name(self: $self, $($arg_name : $arg_ty),*) -> $return {
match self {
FallbackSurface::Preference(dev) => dev.$func_name($($arg_name),*).map_err(EitherError::Either),
FallbackSurface::Fallback(dev) => dev.$func_name($($arg_name),*).map_err(EitherError::Or),
}
}
};
}
impl<D1: Device, D2: Device> AsRawFd for FallbackDevice<D1, D2> {
fallback_device_impl!(as_raw_fd, &Self, RawFd);
@ -243,13 +445,14 @@ impl<D1: Device, D2: Device> AsRawFd for FallbackDevice<D1, D2> {
impl<D1: Device + BasicDevice, D2: Device + BasicDevice> BasicDevice for FallbackDevice<D1, D2> {}
impl<D1: Device + ControlDevice, D2: Device + ControlDevice> ControlDevice for FallbackDevice<D1, D2> {}
impl<E, C, S1, S2, D1, D2> Device for FallbackDevice<D1, D2>
impl<E1, E2, C, S1, S2, D1, D2> Device for FallbackDevice<D1, D2>
where
// Connectors and Error need to match for both Surfaces
E: std::error::Error + Send + 'static,
// Connectors need to match for both Surfaces
E1: std::error::Error + Send + 'static,
E2: std::error::Error + Send + 'static,
C: IntoIterator<Item = connector::Handle> + 'static,
S1: Surface<Error = E, Connectors = C> + 'static,
S2: Surface<Error = E, Connectors = C> + 'static,
S1: Surface<Error = E1, Connectors = C> + 'static,
S2: Surface<Error = E2, Connectors = C> + 'static,
D1: Device<Surface = S1> + 'static,
D2: Device<Surface = S2> + 'static,
{
@ -268,18 +471,20 @@ where
crtc: crtc::Handle,
mode: Mode,
connectors: &[connector::Handle],
) -> Result<Self::Surface, E> {
) -> Result<Self::Surface, EitherError<E1, E2>> {
match self {
FallbackDevice::Preference(dev) => Ok(FallbackSurface::Preference(
dev.create_surface(crtc, mode, connectors)?,
dev.create_surface(crtc, mode, connectors)
.map_err(EitherError::Either)?,
)),
FallbackDevice::Fallback(dev) => Ok(FallbackSurface::Fallback(
dev.create_surface(crtc, mode, connectors)?,
dev.create_surface(crtc, mode, connectors)
.map_err(EitherError::Or)?,
)),
}
}
fallback_device_impl!(process_events, &mut Self);
fallback_device_impl!(resource_handles, &Self, Result<ResourceHandles, E>);
fallback_device_err_impl!(resource_handles, &Self, Result<ResourceHandles, EitherError<E1, E2>>);
fallback_device_impl!(get_connector_info, &Self, Result<connector::Info, DrmError>, conn: connector::Handle);
fallback_device_impl!(get_crtc_info, &Self, Result<crtc::Info, DrmError>, crtc: crtc::Handle);
fallback_device_impl!(get_encoder_info, &Self, Result<encoder::Info, DrmError>, enc: encoder::Handle);
@ -288,13 +493,14 @@ where
}
// Impl RawDevice where underlying types implement RawDevice
impl<E, C, S1, S2, D1, D2> RawDevice for FallbackDevice<D1, D2>
impl<E1, E2, C, S1, S2, D1, D2> RawDevice for FallbackDevice<D1, D2>
where
// Connectors and Error need to match for both Surfaces
E: std::error::Error + Send + 'static,
// Connectors need to match for both Surfaces
E1: std::error::Error + Send + 'static,
E2: std::error::Error + Send + 'static,
C: IntoIterator<Item = connector::Handle> + 'static,
S1: RawSurface + Surface<Error = E, Connectors = C> + 'static,
S2: RawSurface + Surface<Error = E, Connectors = C> + 'static,
S1: RawSurface + Surface<Error = E1, Connectors = C> + 'static,
S2: RawSurface + Surface<Error = E2, Connectors = C> + 'static,
D1: RawDevice<Surface = S1> + 'static,
D2: RawDevice<Surface = S2> + 'static,
{
@ -308,41 +514,47 @@ impl<D1: Device + EGLGraphicsBackend + 'static, D2: Device + EGLGraphicsBackend
fallback_device_impl!(bind_wl_display, &Self, Result<EGLBufferReader, EGLError>, display : &Display);
}
impl<E, C, S1, S2> Surface for FallbackSurface<S1, S2>
impl<E1, E2, C, S1, S2> Surface for FallbackSurface<S1, S2>
where
// Connectors and Error need to match for both Surfaces
E: std::error::Error + Send + 'static,
// Connectors need to match for both Surfaces
E1: std::error::Error + Send + 'static,
E2: std::error::Error + Send + 'static,
C: IntoIterator<Item = connector::Handle> + 'static,
S1: Surface<Error = E, Connectors = C> + 'static,
S2: Surface<Error = E, Connectors = C> + 'static,
S1: Surface<Error = E1, Connectors = C> + 'static,
S2: Surface<Error = E2, Connectors = C> + 'static,
{
type Error = E;
type Error = EitherError<E1, E2>;
type Connectors = C;
fallback_surface_impl!(crtc, &Self, crtc::Handle);
fallback_surface_impl!(current_connectors, &Self, C);
fallback_surface_impl!(pending_connectors, &Self, C);
fallback_surface_impl!(add_connector, &Self, Result<(), E>, conn: connector::Handle);
fallback_surface_impl!(remove_connector, &Self, Result<(), E>, conn: connector::Handle);
fallback_surface_impl!(set_connectors, &Self, Result<(), E>, conns: &[connector::Handle]);
fallback_surface_err_impl!(add_connector, &Self, Result<(), EitherError<E1, E2>>, conn: connector::Handle);
fallback_surface_err_impl!(remove_connector, &Self, Result<(), EitherError<E1, E2>>, conn: connector::Handle);
fallback_surface_err_impl!(set_connectors, &Self, Result<(), EitherError<E1, E2>>, conns: &[connector::Handle]);
fallback_surface_impl!(current_mode, &Self, Mode);
fallback_surface_impl!(pending_mode, &Self, Mode);
fallback_surface_impl!(use_mode, &Self, Result<(), E>, mode: Mode);
fallback_surface_err_impl!(use_mode, &Self, Result<(), EitherError<E1, E2>>, mode: Mode);
}
impl<E, C, S1, S2> RawSurface for FallbackSurface<S1, S2>
impl<E1, E2, C, S1, S2> RawSurface for FallbackSurface<S1, S2>
where
E: std::error::Error + Send + 'static,
E1: std::error::Error + Send + 'static,
E2: std::error::Error + Send + 'static,
C: IntoIterator<Item = connector::Handle> + 'static,
S1: RawSurface + Surface<Error = E, Connectors = C> + 'static,
S2: RawSurface + Surface<Error = E, Connectors = C> + 'static,
S1: RawSurface + Surface<Error = E1, Connectors = C> + 'static,
S2: RawSurface + Surface<Error = E2, Connectors = C> + 'static,
{
fallback_surface_impl!(commit_pending, &Self, bool);
fallback_surface_impl!(commit, &Self, Result<(), E>, fb: framebuffer::Handle);
fn page_flip(&self, framebuffer: framebuffer::Handle) -> Result<(), E> {
fallback_surface_err_impl!(commit, &Self, Result<(), EitherError<E1, E2>>, fb: framebuffer::Handle);
fn page_flip(&self, framebuffer: framebuffer::Handle) -> Result<(), EitherError<E1, E2>> {
match self {
FallbackSurface::Preference(dev) => RawSurface::page_flip(dev, framebuffer),
FallbackSurface::Fallback(dev) => RawSurface::page_flip(dev, framebuffer),
FallbackSurface::Preference(dev) => {
RawSurface::page_flip(dev, framebuffer).map_err(EitherError::Either)
}
FallbackSurface::Fallback(dev) => {
RawSurface::page_flip(dev, framebuffer).map_err(EitherError::Or)
}
}
}
}
@ -353,29 +565,32 @@ impl<S1: Surface + AsRawFd, S2: Surface + AsRawFd> AsRawFd for FallbackSurface<S
impl<S1: Surface + BasicDevice, S2: Surface + BasicDevice> BasicDevice for FallbackSurface<S1, S2> {}
impl<S1: Surface + ControlDevice, S2: Surface + ControlDevice> ControlDevice for FallbackSurface<S1, S2> {}
impl<E1, E2, C, CF, S1, S2> CursorBackend for FallbackSurface<S1, S2>
impl<E1, E2, E3, E4, C, CF, S1, S2> CursorBackend for FallbackSurface<S1, S2>
where
E1: std::error::Error + Send + 'static,
E2: 'static,
E2: std::error::Error + Send + 'static,
E3: std::error::Error + 'static,
E4: std::error::Error + 'static,
CF: ?Sized,
C: IntoIterator<Item = connector::Handle> + 'static,
S1: Surface<Error = E1, Connectors = C> + CursorBackend<CursorFormat = CF, Error = E2> + 'static,
S2: Surface<Error = E1, Connectors = C> + CursorBackend<CursorFormat = CF, Error = E2> + 'static,
S1: Surface<Error = E1, Connectors = C> + CursorBackend<CursorFormat = CF, Error = E3> + 'static,
S2: Surface<Error = E2, Connectors = C> + CursorBackend<CursorFormat = CF, Error = E4> + 'static,
{
type CursorFormat = CF;
type Error = E2;
type Error = EitherError<E3, E4>;
fallback_surface_impl!(set_cursor_position, &Self, Result<(), E2>, x: u32, y: u32);
fallback_surface_impl!(set_cursor_representation, &Self, Result<(), E2>, buffer: &Self::CursorFormat, hotspot: (u32, u32));
fallback_surface_err_impl!(set_cursor_position, &Self, Result<(), EitherError<E3, E4>>, x: u32, y: u32);
fallback_surface_err_impl!(set_cursor_representation, &Self, Result<(), EitherError<E3, E4>>, buffer: &Self::CursorFormat, hotspot: (u32, u32));
}
#[cfg(feature = "renderer_gl")]
impl<E, C, S1, S2> GLGraphicsBackend for FallbackSurface<S1, S2>
impl<E1, E2, C, S1, S2> GLGraphicsBackend for FallbackSurface<S1, S2>
where
E: std::error::Error + Send + 'static,
E1: std::error::Error + Send + 'static,
E2: std::error::Error + Send + 'static,
C: IntoIterator<Item = connector::Handle> + 'static,
S1: Surface<Error = E, Connectors = C> + GLGraphicsBackend + 'static,
S2: Surface<Error = E, Connectors = C> + GLGraphicsBackend + 'static,
S1: Surface<Error = E1, Connectors = C> + GLGraphicsBackend + 'static,
S2: Surface<Error = E2, Connectors = C> + GLGraphicsBackend + 'static,
{
fallback_surface_impl!(swap_buffers, &Self, Result<(), SwapBuffersError>);
fallback_surface_impl!(get_proc_address, &Self, *const c_void, symbol: &str);

View File

@ -46,7 +46,7 @@ pub enum Error<U: std::error::Error + std::fmt::Debug + std::fmt::Display + 'sta
Underlying(#[source] U),
}
type Arguments = (crtc::Handle, Mode, Vec<connector::Handle>);
pub(crate) type Arguments = (crtc::Handle, Mode, Vec<connector::Handle>);
type BackendRef<D> = Weak<EglSurfaceInternal<<D as Device>::Surface>>;
/// Representation of an egl device to create egl rendering surfaces