diff --git a/Cargo.toml b/Cargo.toml index 9687e9d..2320321 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,7 @@ pkg-config = { version = "0.3.17", optional = true } [features] default = ["backend_drm", "backend_gbm", "backend_libinput", "backend_udev", "backend_session_logind", "backend_winit", "renderer_gl", "xwayland", "wayland_frontend", "slog-stdlog"] -backend_winit = ["winit", "wayland-server/dlopen", "backend_egl", "wayland-egl", "renderer_gl", "use_system_lib"] +backend_winit = ["winit", "wayland-server/dlopen", "backend_egl", "wayland-egl", "renderer_gl"] backend_drm = ["drm", "drm-ffi"] backend_gbm = ["gbm"] backend_egl = ["gl_generator"] diff --git a/anvil/src/drawing.rs b/anvil/src/drawing.rs index fbaafe8..cf17a87 100644 --- a/anvil/src/drawing.rs +++ b/anvil/src/drawing.rs @@ -5,8 +5,7 @@ use std::cell::RefCell; use slog::Logger; use smithay::{ backend::{ - egl::display::EGLBufferReader, - renderer::{Frame, Renderer, Texture, Transform}, + renderer::{Frame, Renderer, Texture, Transform, ImportShm, BufferType, buffer_type}, SwapBuffersError, }, reexports::wayland_server::protocol::{wl_buffer, wl_surface}, @@ -17,6 +16,16 @@ use smithay::{ seat::CursorImageRole, }, }; +#[cfg(feature = "egl")] +use smithay::backend::{ + egl::display::EGLBufferReader, + renderer::ImportEgl +}; +// hacky... +#[cfg(not(feature = "egl"))] +pub trait ImportEgl {} +#[cfg(not(feature = "egl"))] +impl ImportEgl for T {} use crate::shell::{MyCompositorToken, MyWindowMap, SurfaceData}; @@ -37,13 +46,14 @@ pub fn draw_cursor( renderer: &mut R, frame: &mut F, surface: &wl_surface::WlSurface, + #[cfg(feature = "egl")] egl_buffer_reader: Option<&EGLBufferReader>, (x, y): (i32, i32), token: MyCompositorToken, log: &Logger, ) -> Result<(), SwapBuffersError> where - R: Renderer, + R: Renderer + ImportShm + ImportEgl, F: Frame, E: std::error::Error + Into, T: Texture + 'static, @@ -62,6 +72,7 @@ where renderer, frame, surface, + #[cfg(feature = "egl")] egl_buffer_reader, (x - dx, y - dy), token, @@ -73,13 +84,14 @@ fn draw_surface_tree( renderer: &mut R, frame: &mut F, root: &wl_surface::WlSurface, + #[cfg(feature = "egl")] egl_buffer_reader: Option<&EGLBufferReader>, location: (i32, i32), compositor_token: MyCompositorToken, log: &Logger, ) -> Result<(), SwapBuffersError> where - R: Renderer, + R: Renderer + ImportShm + ImportEgl, F: Frame, E: std::error::Error + Into, T: Texture + 'static, @@ -95,37 +107,45 @@ where let mut data = data.borrow_mut(); if data.texture.is_none() { if let Some(buffer) = data.current_state.buffer.take() { - let damage = attributes - .damage - .iter() - .map(|dmg| match dmg { - Damage::Buffer(rect) => *rect, - // TODO also apply transformations - Damage::Surface(rect) => rect.scale(attributes.buffer_scale), - }) - .collect::>(); - match renderer.import_buffer(&buffer, Some(&attributes), &damage, egl_buffer_reader) { - Ok(m) => { - let buffer = if smithay::wayland::shm::with_buffer_contents( - &buffer, - |_, _| (), - ) - .is_ok() - { + let texture = match buffer_type( + &buffer, + #[cfg(feature = "egl")] + egl_buffer_reader + ) { + Some(BufferType::Shm) => { + let damage = attributes + .damage + .iter() + .map(|dmg| match dmg { + Damage::Buffer(rect) => *rect, + // TODO also apply transformations + Damage::Surface(rect) => rect.scale(attributes.buffer_scale), + }) + .collect::>(); + let result = renderer.import_shm_buffer(&buffer, Some(&attributes), &damage); + if result.is_ok() { buffer.release(); - None - } else { - Some(buffer) - }; - data.texture = Some(Box::new(BufferTextures { buffer, texture: m }) + } + Some(result) + }, + #[cfg(feature = "egl")] + Some(BufferType::Egl) => Some(renderer.import_egl_buffer(&buffer, egl_buffer_reader.unwrap())), + _ => { + error!(log, "Unknown buffer format for: {:?}", buffer); + None + } + }; + match texture { + Some(Ok(m)) => { + data.texture = Some(Box::new(BufferTextures { buffer: Some(buffer), texture: m }) as Box) } - // there was an error reading the buffer, release it, we - // already logged the error - Err(err) => { + // there was an error reading the buffer, release it. + Some(Err(err)) => { warn!(log, "Error loading buffer: {:?}", err); buffer.release(); - } + }, + None => buffer.release(), }; } } @@ -181,6 +201,7 @@ where pub fn draw_windows( renderer: &mut R, frame: &mut F, + #[cfg(feature = "egl")] egl_buffer_reader: Option<&EGLBufferReader>, window_map: &MyWindowMap, output_rect: Option, @@ -188,7 +209,7 @@ pub fn draw_windows( log: &::slog::Logger, ) -> Result<(), SwapBuffersError> where - R: Renderer, + R: Renderer + ImportShm + ImportEgl, F: Frame, E: std::error::Error + Into, T: Texture + 'static, @@ -210,6 +231,7 @@ where renderer, frame, &wl_surface, + #[cfg(feature = "egl")] egl_buffer_reader, initial_place, compositor_token, @@ -227,13 +249,14 @@ pub fn draw_dnd_icon( renderer: &mut R, frame: &mut F, surface: &wl_surface::WlSurface, + #[cfg(feature = "egl")] egl_buffer_reader: Option<&EGLBufferReader>, (x, y): (i32, i32), token: MyCompositorToken, log: &::slog::Logger, ) -> Result<(), SwapBuffersError> where - R: Renderer, + R: Renderer + ImportShm + ImportEgl, F: Frame, E: std::error::Error + Into, T: Texture + 'static, @@ -244,5 +267,14 @@ where "Trying to display as a dnd icon a surface that does not have the DndIcon role." ); } - draw_surface_tree(renderer, frame, surface, egl_buffer_reader, (x, y), token, log) + draw_surface_tree( + renderer, + frame, + surface, + #[cfg(feature = "egl")] + egl_buffer_reader, + (x, y), + token, + log + ) } diff --git a/anvil/src/input_handler.rs b/anvil/src/input_handler.rs index b70fc1b..7170258 100644 --- a/anvil/src/input_handler.rs +++ b/anvil/src/input_handler.rs @@ -1,6 +1,10 @@ use std::{process::Command, sync::atomic::Ordering}; -use crate::{udev::UdevData, winit::WinitData, AnvilState}; +use crate::AnvilState; +#[cfg(feature = "udev")] +use crate::udev::UdevData; +#[cfg(feature = "winit")] +use crate::winit::WinitData; use smithay::{ backend::input::{ diff --git a/anvil/src/shell.rs b/anvil/src/shell.rs index 1e48f1d..ad72e92 100644 --- a/anvil/src/shell.rs +++ b/anvil/src/shell.rs @@ -839,7 +839,7 @@ fn surface_commit( } #[cfg(not(feature = "egl"))] { - next_state.dimensions = buffer_dimensions(&buffer, None); + next_state.dimensions = buffer_dimensions(&buffer); } next_state.buffer = Some(buffer); } diff --git a/anvil/src/state.rs b/anvil/src/state.rs index 1b4db20..f305c8f 100644 --- a/anvil/src/state.rs +++ b/anvil/src/state.rs @@ -84,10 +84,7 @@ impl AnvilState { init_shm_global(&mut (*display).borrow_mut(), vec![], log.clone()); - #[cfg(feature = "egl")] let shell_handles = init_shell::(&mut display.borrow_mut(), log.clone()); - #[cfg(not(feature = "egl"))] - let shell_handles = init_shell(&mut display.borrow_mut(), log.clone()); let socket_name = display .borrow_mut() diff --git a/anvil/src/udev.rs b/anvil/src/udev.rs index af0e076..5845f6f 100644 --- a/anvil/src/udev.rs +++ b/anvil/src/udev.rs @@ -110,6 +110,7 @@ pub fn run_udev( * Initialize the compositor */ let pointer_bytes = include_bytes!("../resources/cursor2.rgba"); + #[cfg(feature = "egl")] let primary_gpu = primary_gpu(&session.seat()).unwrap_or_default(); // setup the timer @@ -118,6 +119,7 @@ pub fn run_udev( let data = UdevData { session, output_map: Vec::new(), + #[cfg(feature = "egl")] primary_gpu, backends: HashMap::new(), signaler: session_signal.clone(), @@ -669,9 +671,6 @@ fn render_surface( cursor_status: &mut CursorImageStatus, logger: &slog::Logger, ) -> Result<(), SwapBuffersError> { - #[cfg(not(feature = "egl"))] - let egl_buffer_reader = None; - surface.frame_submitted()?; // get output coordinates @@ -693,6 +692,7 @@ fn render_surface( draw_windows( renderer, frame, + #[cfg(feature = "egl")] egl_buffer_reader, window_map, Some(Rectangle { @@ -720,6 +720,7 @@ fn render_surface( renderer, frame, wl_surface, + #[cfg(feature = "egl")] egl_buffer_reader, (ptr_x, ptr_y), *compositor_token, @@ -744,6 +745,7 @@ fn render_surface( renderer, frame, wl_surface, + #[cfg(feature = "egl")] egl_buffer_reader, (ptr_x, ptr_y), *compositor_token, diff --git a/anvil/src/winit.rs b/anvil/src/winit.rs index e4466f6..c69c45d 100644 --- a/anvil/src/winit.rs +++ b/anvil/src/winit.rs @@ -37,9 +37,6 @@ pub fn run_winit( #[cfg(feature = "egl")] let reader = renderer.borrow().bind_wl_display(&display.borrow()).ok(); - #[cfg(not(feature = "egl"))] - let reader = None; - #[cfg(feature = "egl")] if reader.is_some() { info!(log, "EGL hardware-acceleration enabled"); @@ -114,6 +111,7 @@ pub fn run_winit( draw_windows( renderer, frame, + #[cfg(feature = "egl")] state.egl_reader.as_ref(), &*state.window_map.borrow(), None, @@ -131,6 +129,7 @@ pub fn run_winit( renderer, frame, surface, + #[cfg(feature = "egl")] state.egl_reader.as_ref(), (x as i32, y as i32), state.ctoken, @@ -158,6 +157,7 @@ pub fn run_winit( renderer, frame, surface, + #[cfg(feature = "egl")] state.egl_reader.as_ref(), (x as i32, y as i32), state.ctoken, diff --git a/src/backend/renderer/gles2/mod.rs b/src/backend/renderer/gles2/mod.rs index fffeca0..183915e 100644 --- a/src/backend/renderer/gles2/mod.rs +++ b/src/backend/renderer/gles2/mod.rs @@ -1,7 +1,5 @@ //! Implementation of the rendering traits using OpenGL ES 2 -#[cfg(feature = "wayland_frontend")] -use std::cell::RefCell; use std::collections::HashMap; use std::convert::TryFrom; use std::ffi::CStr; @@ -32,12 +30,17 @@ use crate::backend::SwapBuffersError; #[cfg(feature = "wayland_frontend")] use crate::{ - backend::egl::display::EGLBufferReader, utils::Rectangle, wayland::compositor::SurfaceAttributes, + utils::Rectangle, + wayland::compositor::SurfaceAttributes, }; -#[cfg(feature = "wayland_frontend")] -use wayland_commons::user_data::UserDataMap; +#[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))] +use crate::backend::egl::display::EGLBufferReader; #[cfg(feature = "wayland_frontend")] use wayland_server::protocol::{wl_buffer, wl_shm}; +#[cfg(feature = "wayland_frontend")] +use super::ImportShm; +#[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))] +use super::ImportEgl; #[allow(clippy::all, missing_docs)] pub mod ffi { @@ -221,10 +224,6 @@ pub enum Gles2Error { #[error("Error accessing the buffer ({0:?})")] #[cfg(feature = "wayland_frontend")] EGLBufferAccessError(crate::backend::egl::BufferAccessError), - /// The buffer backend is unknown or unsupported - #[error("Error accessing the buffer")] - #[cfg(feature = "wayland_frontend")] - UnknownBufferType, /// This rendering operation was called without a previous `begin`-call #[error("Call begin before doing any rendering operations")] UnconstraintRenderingOperation, @@ -243,7 +242,6 @@ impl From for SwapBuffersError { x @ Gles2Error::FramebufferBindingError | x @ Gles2Error::BindBufferEGLError(_) | x @ Gles2Error::UnsupportedPixelFormat(_) - | x @ Gles2Error::UnknownBufferType | x @ Gles2Error::BufferAccessError(_) | x @ Gles2Error::EGLBufferAccessError(_) => SwapBuffersError::TemporaryFailure(Box::new(x)), } @@ -500,9 +498,9 @@ impl Gles2Renderer { } } -impl Gles2Renderer { - #[cfg(feature = "wayland_frontend")] - fn import_shm( +#[cfg(feature = "wayland_frontend")] +impl ImportShm for Gles2Renderer { + fn import_shm_buffer( &mut self, buffer: &wl_buffer::WlBuffer, surface: Option<&SurfaceAttributes>, @@ -613,7 +611,19 @@ impl Gles2Renderer { } #[cfg(feature = "wayland_frontend")] - fn import_egl( + fn shm_formats(&self) -> &[wl_shm::Format] { + &[ + wl_shm::Format::Abgr8888, + wl_shm::Format::Xbgr8888, + wl_shm::Format::Argb8888, + wl_shm::Format::Xrgb8888, + ] + } +} + +#[cfg(all(feature = "wayland_frontend", feature = "backend_egl", feature = "use_system_lib"))] +impl ImportEgl for Gles2Renderer { + fn import_egl_buffer( &mut self, buffer: &wl_buffer::WlBuffer, reader: &EGLBufferReader, @@ -654,8 +664,10 @@ impl Gles2Renderer { Ok(texture) } +} - #[cfg(feature = "wayland_frontend")] +#[cfg(feature = "wayland_frontend")] +impl Gles2Renderer { fn existing_dmabuf_texture( &self, buffer: &wl_buffer::WlBuffer, @@ -880,16 +892,6 @@ impl Renderer for Gles2Renderer { type TextureId = Gles2Texture; type Frame = Gles2Frame; - #[cfg(feature = "wayland_frontend")] - fn shm_formats(&self) -> &[wl_shm::Format] { - &[ - wl_shm::Format::Abgr8888, - wl_shm::Format::Xbgr8888, - wl_shm::Format::Argb8888, - wl_shm::Format::Xrgb8888, - ] - } - #[cfg(feature = "image")] fn import_bitmap>( &mut self, @@ -935,40 +937,6 @@ impl Renderer for Gles2Renderer { Ok(texture) } - #[cfg(feature = "wayland_frontend")] - fn import_buffer( - &mut self, - buffer: &wl_buffer::WlBuffer, - surface: Option<&SurfaceAttributes>, - damage: &[Rectangle], - egl: Option<&EGLBufferReader>, - ) -> Result { - let texture = if egl.and_then(|egl| egl.egl_buffer_dimensions(&buffer)).is_some() { - self.import_egl(&buffer, egl.unwrap()) - } else if crate::wayland::shm::with_buffer_contents(&buffer, |_, _| ()).is_ok() { - self.import_shm(&buffer, surface, damage) - } else { - Err(Gles2Error::UnknownBufferType) - }?; - - // we want to keep the texture alive for as long as the buffer is alive. - // otherwise `existing_texture` will not work, - // if the user does not keep the texture alive long enough. - buffer.as_ref().user_data().set_threadsafe(|| UserDataMap::new()); - if let Some(map) = buffer.as_ref().user_data().get::() { - map.insert_if_missing(|| Vec::>>::new()); - if let Some(vec) = map.get::>>>() { - let mut vec = vec.borrow_mut(); - while vec.len() < self.id { - vec.push(None); - } - vec[self.id] = Some(texture.clone()); - } - } - - Ok(texture) - } - fn render( &mut self, width: u32, diff --git a/src/backend/renderer/mod.rs b/src/backend/renderer/mod.rs index cd46935..25f467e 100644 --- a/src/backend/renderer/mod.rs +++ b/src/backend/renderer/mod.rs @@ -18,7 +18,7 @@ use wayland_server::protocol::{wl_buffer, wl_shm}; #[cfg(feature = "renderer_gl")] pub mod gles2; -#[cfg(all(feature = "wayland_frontend", feature = "backend_egl"))] +#[cfg(all(feature = "wayland_frontend", feature = "backend_egl", feature = "use_system_lib"))] use crate::backend::egl::display::EGLBufferReader; #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] @@ -216,39 +216,6 @@ pub trait Renderer { image: &image::ImageBuffer, C>, ) -> Result; - /// Returns supported formats for shared memory buffers. - /// - /// Will always contain At least `Argb8888` and `Xrgb8888`. - #[cfg(feature = "wayland_frontend")] - fn shm_formats(&self) -> &[wl_shm::Format] { - // Mandatory - &[wl_shm::Format::Argb8888, wl_shm::Format::Xrgb8888] - } - - /// Import a given buffer into the renderer. - /// - /// Returns a texture_id, which can be used with `render_texture(_at)` or implementation-specific functions. - /// - /// If not otherwise defined by the implementation, this texture id is only valid for the renderer, that created it. - /// - /// This operation needs no bound or default rendering target. - /// - /// The implementation defines, if the id keeps being valid, if the buffer is released, - /// to avoid relying on implementation details, keep the buffer alive, until you destroyed this texture again. - /// - /// If provided the `SurfaceAttributes` can be used to do caching of rendering resources and is generally recommended. - /// - /// The `damage` argument provides a list of rectangle locating parts of the buffer that need to be updated. When provided - /// with an empty list `&[]`, the renderer is allowed to not update the texture at all. - #[cfg(all(feature = "wayland_frontend", feature = "backend_egl"))] - fn import_buffer( - &mut self, - buffer: &wl_buffer::WlBuffer, - surface: Option<&SurfaceAttributes>, - damage: &[Rectangle], - egl: Option<&EGLBufferReader>, - ) -> Result; - /// Initialize a rendering context on the current rendering target with given dimensions and transformation. /// /// This function *may* error, if: @@ -267,6 +234,102 @@ pub trait Renderer { F: FnOnce(&mut Self, &mut Self::Frame) -> R; } +#[cfg(feature = "wayland_frontend")] +/// Trait for Renderers supporting importing shm-based buffers. +pub trait ImportShm: Renderer { + /// Import a given shm-based buffer into the renderer (see [`buffer_type`]). + /// + /// Returns a texture_id, which can be used with [`Frame::render_texture`] (or [`Frame::render_texture_at`]) + /// or implementation-specific functions. + /// + /// If not otherwise defined by the implementation, this texture id is only valid for the renderer, that created it. + /// This operation needs no bound or default rendering target. + /// + /// The implementation defines, if the id keeps being valid, if the buffer is released, + /// to avoid relying on implementation details, keep the buffer alive, until you destroyed this texture again. + /// + /// If provided the `SurfaceAttributes` can be used to do caching of rendering resources and is generally recommended. + /// + /// The `damage` argument provides a list of rectangle locating parts of the buffer that need to be updated. When provided + /// with an empty list `&[]`, the renderer is allowed to not update the texture at all. + fn import_shm_buffer( + &mut self, + buffer: &wl_buffer::WlBuffer, + surface: Option<&SurfaceAttributes>, + damage: &[Rectangle], + ) -> Result<::TextureId, ::Error>; + + /// Returns supported formats for shared memory buffers. + /// + /// Will always contain At least `Argb8888` and `Xrgb8888`. + fn shm_formats(&self) -> &[wl_shm::Format] { + // Mandatory + &[wl_shm::Format::Argb8888, wl_shm::Format::Xrgb8888] + } +} + +#[cfg(all(feature = "wayland_frontend", feature = "backend_egl", feature = "use_system_lib"))] +/// Trait for Renderers supporting importing wl_drm-based buffers. +pub trait ImportEgl: Renderer { + /// Import a given wl_drm-based buffer into the renderer (see [`buffer_type`]). + /// + /// Returns a texture_id, which can be used with [`Frame::render_texture`] (or [`Frame::render_texture_at`]) + /// or implementation-specific functions. + /// + /// If not otherwise defined by the implementation, this texture id is only valid for the renderer, that created it. + /// + /// This operation needs no bound or default rendering target. + /// + /// The implementation defines, if the id keeps being valid, if the buffer is released, + /// to avoid relying on implementation details, keep the buffer alive, until you destroyed this texture again. + fn import_egl_buffer( + &mut self, + buffer: &wl_buffer::WlBuffer, + egl: &EGLBufferReader, + ) -> Result<::TextureId, ::Error>; +} + +// TODO: Replace this with a trait_alias, once that is stabilized. +// pub type ImportAll = Renderer + ImportShm + ImportEgl; + +/// Common trait for renderers of any wayland buffer type +#[cfg(all(feature = "wayland_frontend", feature = "backend_egl", feature = "use_system_lib"))] +pub trait ImportAll: Renderer + ImportShm + ImportEgl { + /// Import a given buffer into the renderer. + /// + /// Returns a texture_id, which can be used with [`Frame::render_texture`] (or [`Frame::render_texture_at`]) + /// or implementation-specific functions. + /// + /// If not otherwise defined by the implementation, this texture id is only valid for the renderer, that created it. + /// + /// This operation needs no bound or default rendering target. + /// + /// The implementation defines, if the id keeps being valid, if the buffer is released, + /// to avoid relying on implementation details, keep the buffer alive, until you destroyed this texture again. + /// + /// If provided the `SurfaceAttributes` can be used to do caching of rendering resources and is generally recommended. + /// + /// The `damage` argument provides a list of rectangle locating parts of the buffer that need to be updated. When provided + /// with an empty list `&[]`, the renderer is allowed to not update the texture at all. + /// + /// Returns `None`, if the buffer type cannot be determined. + fn import_buffer( + &mut self, + buffer: &wl_buffer::WlBuffer, + surface: Option<&SurfaceAttributes>, + damage: &[Rectangle], + egl: Option<&EGLBufferReader>, + ) -> Option::TextureId, ::Error>> { + match buffer_type(buffer, egl) { + Some(BufferType::Shm) => Some(self.import_shm_buffer(buffer, surface, damage)), + Some(BufferType::Egl) => Some(self.import_egl_buffer(buffer, egl.unwrap())), + _ => None, + } + } +} +#[cfg(all(feature = "wayland_frontend", feature = "backend_egl", feature = "use_system_lib"))] +impl ImportAll for R {} + #[cfg(feature = "wayland_frontend")] #[non_exhaustive] /// Buffer type of a given wl_buffer, if managed by smithay @@ -306,7 +369,7 @@ pub fn buffer_type( /// Returns the *type* of a wl_buffer /// /// Returns `None` if the type is not recognized by smithay or otherwise not supported. -#[cfg(all(feature = "wayland_frontend", not(feature = "backend_egl"), not(feature = "use_system_lib")))] +#[cfg(all(feature = "wayland_frontend", not(all(feature = "backend_egl", feature = "use_system_lib"))))] pub fn buffer_type(buffer: &wl_buffer::WlBuffer) -> Option { use crate::backend::allocator::Buffer; @@ -343,7 +406,7 @@ pub fn buffer_dimensions( /// Returns the dimensions of a wl_buffer /// /// *Note*: This will only return dimensions for buffer types known to smithay (see [`buffer_type`]) -#[cfg(all(feature = "wayland_frontend", not(feature = "backend_egl"), not(feature = "use_system_lib")))] +#[cfg(all(feature = "wayland_frontend", not(all(feature = "backend_egl", feature = "use_system_lib"))))] pub fn buffer_dimensions(buffer: &wl_buffer::WlBuffer) -> Option<(i32, i32)> { use crate::backend::allocator::Buffer; diff --git a/src/backend/winit.rs b/src/backend/winit.rs index 4569193..dc957bd 100644 --- a/src/backend/winit.rs +++ b/src/backend/winit.rs @@ -233,13 +233,13 @@ pub enum WinitEvent { Refresh, } -#[cfg(feature = "use_system_lib")] impl WinitGraphicsBackend { /// Bind a `wl_display` to allow hardware-accelerated clients using `wl_drm`. /// /// Returns an `EGLBufferReader` used to access the contents of these buffers. /// /// *Note*: Only on implementation of `wl_drm` can be bound by a single wayland display. + #[cfg(feature = "use_system_lib")] pub fn bind_wl_display(&self, wl_display: &Display) -> Result { self.display.bind_wl_display(wl_display) }