From c578a9e16cdba4cf214c61a003a2bdc80584c126 Mon Sep 17 00:00:00 2001 From: Victor Brekenfeld Date: Thu, 10 Jun 2021 18:13:20 +0200 Subject: [PATCH] Move EGLBufferReader management into ImportEgl --- anvil/src/drawing.rs | 128 +++++++++--------------------- anvil/src/shell.rs | 16 +++- anvil/src/state.rs | 8 +- anvil/src/udev.rs | 59 ++++++-------- anvil/src/winit.rs | 38 ++++----- src/backend/renderer/gles2/mod.rs | 37 +++++++-- src/backend/renderer/mod.rs | 122 ++++++++++++++++++++++++---- 7 files changed, 229 insertions(+), 179 deletions(-) diff --git a/anvil/src/drawing.rs b/anvil/src/drawing.rs index 5b1134e..43c2015 100644 --- a/anvil/src/drawing.rs +++ b/anvil/src/drawing.rs @@ -3,11 +3,9 @@ use std::cell::RefCell; use slog::Logger; -#[cfg(feature = "egl")] -use smithay::backend::{egl::display::EGLBufferReader, renderer::ImportEgl}; use smithay::{ backend::{ - renderer::{buffer_type, BufferType, Frame, ImportDma, ImportShm, Renderer, Texture, Transform}, + renderer::{BufferType, Frame, ImportAll, Renderer, Texture, Transform}, SwapBuffersError, }, reexports::wayland_server::protocol::{wl_buffer, wl_surface}, @@ -18,11 +16,6 @@ use smithay::{ seat::CursorImageRole, }, }; -// hacky... -#[cfg(not(feature = "egl"))] -pub trait ImportEgl {} -#[cfg(not(feature = "egl"))] -impl ImportEgl for T {} use crate::shell::{MyCompositorToken, MyWindowMap, SurfaceData}; @@ -43,13 +36,12 @@ 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 + ImportShm + ImportEgl + ImportDma, + R: Renderer + ImportAll, F: Frame, E: std::error::Error + Into, T: Texture + 'static, @@ -64,29 +56,19 @@ where (0, 0) } }; - draw_surface_tree( - renderer, - frame, - surface, - #[cfg(feature = "egl")] - egl_buffer_reader, - (x - dx, y - dy), - token, - log, - ) + draw_surface_tree(renderer, frame, surface, (x - dx, y - dy), token, log) } 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 + ImportShm + ImportEgl + ImportDma, + R: Renderer + ImportAll, F: Frame, E: std::error::Error + Into, T: Texture + 'static, @@ -102,54 +84,36 @@ where let mut data = data.borrow_mut(); if data.texture.is_none() { if let Some(buffer) = data.current_state.buffer.take() { - 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); - buffer.release(); - // don't return the buffer as it is already released - Some((result, None)) - } - #[cfg(feature = "egl")] - Some(BufferType::Egl) => Some(( - renderer.import_egl_buffer(&buffer, egl_buffer_reader.unwrap()), - Some(buffer), - )), - Some(BufferType::Dma) => { - Some((renderer.import_dma_buffer(&buffer), Some(buffer))) - } - _ => { - error!(log, "Unknown buffer format for: {:?}", buffer); - buffer.release(); - None - } - }; - match texture { - Some((Ok(m), buffer)) => { - data.texture = Some(Box::new(BufferTextures { buffer, texture: m }) - as Box) - } - // there was an error reading the buffer, release it. - Some((Err(err), buffer)) => { - warn!(log, "Error loading buffer: {:?}", err); - if let Some(buffer) = buffer { + 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) { + Some(Ok(m)) => { + if let Some(BufferType::Shm) = renderer.buffer_type(&buffer) { buffer.release(); } + data.texture = Some(Box::new(BufferTextures { + buffer: Some(buffer), + texture: m, + }) + as Box) } - None => {} - }; + Some(Err(err)) => { + warn!(log, "Error loading buffer: {:?}", err); + buffer.release(); + } + None => { + error!(log, "Unknown buffer format for: {:?}", buffer); + buffer.release(); + } + } } } // Now, should we be drawn ? @@ -204,14 +168,13 @@ 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, compositor_token: MyCompositorToken, log: &::slog::Logger, ) -> Result<(), SwapBuffersError> where - R: Renderer + ImportShm + ImportEgl + ImportDma, + R: Renderer + ImportAll, F: Frame, E: std::error::Error + Into, T: Texture + 'static, @@ -229,16 +192,9 @@ where } if let Some(wl_surface) = toplevel_surface.get_surface() { // this surface is a root of a subsurface tree that needs to be drawn - if let Err(err) = draw_surface_tree( - renderer, - frame, - &wl_surface, - #[cfg(feature = "egl")] - egl_buffer_reader, - initial_place, - compositor_token, - log, - ) { + if let Err(err) = + draw_surface_tree(renderer, frame, &wl_surface, initial_place, compositor_token, log) + { result = Err(err); } } @@ -251,13 +207,12 @@ 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 + ImportShm + ImportEgl + ImportDma, + R: Renderer + ImportAll, F: Frame, E: std::error::Error + Into, T: Texture + 'static, @@ -268,14 +223,5 @@ where "Trying to display as a dnd icon a surface that does not have the DndIcon role." ); } - draw_surface_tree( - renderer, - frame, - surface, - #[cfg(feature = "egl")] - egl_buffer_reader, - (x, y), - token, - log, - ) + draw_surface_tree(renderer, frame, surface, (x, y), token, log) } diff --git a/anvil/src/shell.rs b/anvil/src/shell.rs index 3899537..dca36ab 100644 --- a/anvil/src/shell.rs +++ b/anvil/src/shell.rs @@ -37,7 +37,7 @@ use smithay::{ }; use crate::{ - state::AnvilState, + state::{AnvilState, Backend}, window_map::{Kind as SurfaceKind, PopupKind, WindowMap}, }; @@ -324,17 +324,25 @@ pub struct ShellHandles { pub window_map: Rc>, } -pub fn init_shell(display: &mut Display, log: ::slog::Logger) -> ShellHandles { +pub fn init_shell( + display: &mut Display, + log: ::slog::Logger, +) -> ShellHandles { // Create the compositor let (compositor_token, _, _) = compositor_init( display, move |request, surface, ctoken, mut ddata| match request { SurfaceEvent::Commit => { - let anvil_state = ddata.get::>().unwrap(); + let anvil_state = ddata.get::>().unwrap(); let window_map = anvil_state.window_map.as_ref(); #[cfg(feature = "egl")] { - surface_commit(&surface, ctoken, anvil_state.egl_reader.as_ref(), &*window_map) + surface_commit( + &surface, + ctoken, + anvil_state.backend_data.egl_reader().as_ref(), + &*window_map, + ) } #[cfg(not(feature = "egl"))] { diff --git a/anvil/src/state.rs b/anvil/src/state.rs index 29394e0..b2acbd5 100644 --- a/anvil/src/state.rs +++ b/anvil/src/state.rs @@ -45,8 +45,7 @@ pub struct AnvilState { pub cursor_status: Arc>, pub seat_name: String, pub start_time: std::time::Instant, - #[cfg(feature = "egl")] - pub egl_reader: Option, + // things we must keep alive #[cfg(feature = "xwayland")] pub xwayland: XWayland>, } @@ -56,7 +55,6 @@ impl AnvilState { display: Rc>, handle: LoopHandle<'static, AnvilState>, backend_data: BackendData, - #[cfg(feature = "egl")] egl_reader: Option, log: slog::Logger, ) -> AnvilState { // init the wayland connection @@ -170,8 +168,6 @@ impl AnvilState { cursor_status, pointer_location: (0.0, 0.0), seat_name, - #[cfg(feature = "egl")] - egl_reader, start_time: std::time::Instant::now(), #[cfg(feature = "xwayland")] xwayland, @@ -181,4 +177,6 @@ impl AnvilState { pub trait Backend { fn seat_name(&self) -> String; + #[cfg(feature = "egl")] + fn egl_reader(&self) -> Option; } diff --git a/anvil/src/udev.rs b/anvil/src/udev.rs index c2325ee..aab62fa 100644 --- a/anvil/src/udev.rs +++ b/anvil/src/udev.rs @@ -58,7 +58,12 @@ use smithay::{ }; #[cfg(feature = "egl")] use smithay::{ - backend::{drm::DevPath, egl::display::EGLBufferReader, renderer::ImportDma, udev::primary_gpu}, + backend::{ + drm::DevPath, + egl::display::EGLBufferReader, + renderer::{ImportDma, ImportEgl}, + udev::primary_gpu, + }, wayland::dmabuf::init_dmabuf_global, }; @@ -86,6 +91,12 @@ pub struct UdevData { } impl Backend for UdevData { + #[cfg(feature = "egl")] + fn egl_reader(&self) -> Option { + self.backends + .values() + .find_map(|backend| backend.renderer.borrow().egl_reader().cloned()) + } fn seat_name(&self) -> String { self.session.seat() } @@ -130,14 +141,7 @@ pub fn run_udev( pointer_image: ImageBuffer::from_raw(64, 64, pointer_bytes.to_vec()).unwrap(), render_timer: timer.handle(), }; - let mut state = AnvilState::init( - display.clone(), - event_loop.handle(), - data, - #[cfg(feature = "egl")] - None, - log.clone(), - ); + let mut state = AnvilState::init(display.clone(), event_loop.handle(), data, log.clone()); // re-render timer event_loop @@ -460,17 +464,6 @@ impl AnvilState { } }; - #[cfg(feature = "egl")] - let is_primary = path.canonicalize().ok() == self.backend_data.primary_gpu; - // init hardware acceleration on the primary gpu. - #[cfg(feature = "egl")] - { - if is_primary { - info!(self.log, "Initializing EGL Hardware Acceleration via {:?}", path); - self.egl_reader = egl.bind_wl_display(&*self.display.borrow()).ok(); - } - } - let context = match EGLContext::new(&egl, self.log.clone()) { Ok(context) => context, Err(err) => { @@ -486,6 +479,15 @@ impl AnvilState { Gles2Renderer::new(context, self.log.clone()).unwrap() })); + #[cfg(feature = "egl")] + if path.canonicalize().ok() == self.backend_data.primary_gpu { + info!(self.log, "Initializing EGL Hardware Acceleration via {:?}", path); + renderer + .borrow_mut() + .bind_wl_display(&*self.display.borrow()) + .expect("Unable to bind Wl Display?"); + } + let backends = Rc::new(RefCell::new(scan_connectors( &mut device, &gbm, @@ -597,12 +599,8 @@ impl AnvilState { // don't use hardware acceleration anymore, if this was the primary gpu #[cfg(feature = "egl")] - { - if _device.dev_path().and_then(|path| path.canonicalize().ok()) - == self.backend_data.primary_gpu - { - self.egl_reader = None; - } + if _device.dev_path().and_then(|path| path.canonicalize().ok()) == self.backend_data.primary_gpu { + backend_data.renderer.borrow_mut().unbind_wl_display(); } debug!(self.log, "Dropping device"); } @@ -637,8 +635,6 @@ impl AnvilState { let result = render_surface( &mut *surface.borrow_mut(), &mut *device_backend.renderer.borrow_mut(), - #[cfg(feature = "egl")] - self.egl_reader.as_ref(), device_backend.dev_id, crtc, &mut *self.window_map.borrow_mut(), @@ -687,7 +683,6 @@ impl AnvilState { fn render_surface( surface: &mut RenderSurface, renderer: &mut Gles2Renderer, - #[cfg(feature = "egl")] egl_buffer_reader: Option<&EGLBufferReader>, device_id: dev_t, crtc: crtc::Handle, window_map: &mut MyWindowMap, @@ -726,8 +721,6 @@ fn render_surface( draw_windows( renderer, frame, - #[cfg(feature = "egl")] - egl_buffer_reader, window_map, Some(Rectangle { x: x as i32, @@ -754,8 +747,6 @@ fn render_surface( renderer, frame, wl_surface, - #[cfg(feature = "egl")] - egl_buffer_reader, (ptr_x, ptr_y), *compositor_token, logger, @@ -779,8 +770,6 @@ fn render_surface( renderer, frame, wl_surface, - #[cfg(feature = "egl")] - egl_buffer_reader, (ptr_x, ptr_y), *compositor_token, logger, diff --git a/anvil/src/winit.rs b/anvil/src/winit.rs index 02f4b14..1451f08 100644 --- a/anvil/src/winit.rs +++ b/anvil/src/winit.rs @@ -1,7 +1,13 @@ use std::{cell::RefCell, rc::Rc, sync::atomic::Ordering, time::Duration}; #[cfg(feature = "egl")] -use smithay::{backend::renderer::ImportDma, wayland::dmabuf::init_dmabuf_global}; +use smithay::{ + backend::{ + egl::display::EGLBufferReader, + renderer::{ImportDma, ImportEgl}, + }, + wayland::dmabuf::init_dmabuf_global, +}; use smithay::{ backend::{input::InputBackend, renderer::Frame, winit, SwapBuffersError}, reexports::{ @@ -19,9 +25,14 @@ use slog::Logger; use crate::drawing::*; use crate::state::{AnvilState, Backend}; -pub struct WinitData; +pub struct WinitData(Rc>); impl Backend for WinitData { + #[cfg(feature = "egl")] + fn egl_reader(&self) -> Option { + self.0.borrow_mut().renderer().egl_reader().cloned() + } + fn seat_name(&self) -> String { String::from("winit") } @@ -38,9 +49,7 @@ pub fn run_winit( let renderer = Rc::new(RefCell::new(renderer)); #[cfg(feature = "egl")] - let reader = renderer.borrow().bind_wl_display(&display.borrow()).ok(); - #[cfg(feature = "egl")] - if reader.is_some() { + if renderer.borrow().bind_wl_display(&display.borrow()).is_ok() { info!(log, "EGL hardware-acceleration enabled"); let dmabuf_formats = renderer .borrow_mut() @@ -66,9 +75,7 @@ pub fn run_winit( let mut state = AnvilState::init( display.clone(), event_loop.handle(), - WinitData, - #[cfg(feature = "egl")] - reader, + WinitData(renderer.clone()), log.clone(), ); @@ -129,8 +136,6 @@ pub fn run_winit( draw_windows( renderer, frame, - #[cfg(feature = "egl")] - state.egl_reader.as_ref(), &*state.window_map.borrow(), None, state.ctoken, @@ -147,8 +152,6 @@ pub fn run_winit( renderer, frame, surface, - #[cfg(feature = "egl")] - state.egl_reader.as_ref(), (x as i32, y as i32), state.ctoken, &log, @@ -171,16 +174,7 @@ pub fn run_winit( // draw as relevant if let CursorImageStatus::Image(ref surface) = *guard { cursor_visible = false; - draw_cursor( - renderer, - frame, - surface, - #[cfg(feature = "egl")] - state.egl_reader.as_ref(), - (x as i32, y as i32), - state.ctoken, - &log, - )?; + draw_cursor(renderer, frame, surface, (x as i32, y as i32), state.ctoken, &log)?; } else { cursor_visible = true; } diff --git a/src/backend/renderer/gles2/mod.rs b/src/backend/renderer/gles2/mod.rs index 491f2d4..b82a55f 100644 --- a/src/backend/renderer/gles2/mod.rs +++ b/src/backend/renderer/gles2/mod.rs @@ -152,6 +152,8 @@ pub struct Gles2Renderer { #[cfg(feature = "wayland_frontend")] dmabuf_cache: HashMap, egl: EGLContext, + #[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))] + egl_reader: Option, gl: ffi::Gles2, destruction_callback: Receiver, destruction_callback_sender: Sender, @@ -446,6 +448,8 @@ impl Gles2Renderer { id: RENDERER_COUNTER.fetch_add(1, Ordering::SeqCst), gl, egl: context, + #[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))] + egl_reader: None, extensions: exts, programs, target_buffer: None, @@ -619,15 +623,33 @@ impl ImportShm for Gles2Renderer { feature = "use_system_lib" ))] impl ImportEgl for Gles2Renderer { - fn import_egl_buffer( + fn bind_wl_display( &mut self, - buffer: &wl_buffer::WlBuffer, - reader: &EGLBufferReader, - ) -> Result { + display: &wayland_server::Display, + ) -> Result<(), crate::backend::egl::Error> { + self.egl_reader = Some(self.egl.display.bind_wl_display(display)?); + Ok(()) + } + + fn unbind_wl_display(&mut self) { + self.egl_reader = None; + } + + fn egl_reader(&self) -> Option<&EGLBufferReader> { + self.egl_reader.as_ref() + } + + fn import_egl_buffer(&mut self, buffer: &wl_buffer::WlBuffer) -> Result { if !self.extensions.iter().any(|ext| ext == "GL_OES_EGL_image") { return Err(Gles2Error::GLExtensionNotSupported(&["GL_OES_EGL_image"])); } + if self.egl_reader().is_none() { + return Err(Gles2Error::EGLBufferAccessError( + crate::backend::egl::BufferAccessError::NotManaged(crate::backend::egl::EGLError::BadDisplay), + )); + } + // We can not use the caching logic for textures here as the // egl buffers a potentially managed external which will fail the // clean up check if the buffer is still alive. For wl_drm the @@ -635,7 +657,10 @@ impl ImportEgl for Gles2Renderer { // will never be cleaned up. self.make_current()?; - let egl = reader + let egl = self + .egl_reader + .as_ref() + .unwrap() .egl_buffer_contents(&buffer) .map_err(Gles2Error::EGLBufferAccessError)?; @@ -905,6 +930,8 @@ impl Drop for Gles2Renderer { let _ = Box::from_raw(logger_ptr); } + #[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))] + let _ = self.egl_reader.take(); let _ = self.egl.unbind(); } } diff --git a/src/backend/renderer/mod.rs b/src/backend/renderer/mod.rs index e8ac8d0..ed37e32 100644 --- a/src/backend/renderer/mod.rs +++ b/src/backend/renderer/mod.rs @@ -25,7 +25,7 @@ use crate::backend::allocator::{dmabuf::Dmabuf, Format}; feature = "backend_egl", feature = "use_system_lib" ))] -use crate::backend::egl::display::EGLBufferReader; +use crate::backend::egl::{display::EGLBufferReader, Error as EglError}; #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] /// Possible transformations to two-dimensional planes @@ -281,6 +281,34 @@ pub trait ImportShm: Renderer { ))] /// Trait for Renderers supporting importing wl_drm-based buffers. pub trait ImportEgl: Renderer { + /// Binds the underlying EGL display to the given Wayland display. + /// + /// This will allow clients to utilize EGL to create hardware-accelerated + /// surfaces. This renderer will thus be able to handle wl_drm-based buffers. + /// + /// ## Errors + /// + /// This might return [`EglExtensionNotSupported`](Error::EglExtensionNotSupported) + /// if binding is not supported by the EGL implementation. + /// + /// This might return [`OtherEGLDisplayAlreadyBound`](Error::OtherEGLDisplayAlreadyBound) + /// if called for the same [`Display`] multiple times, as only one egl display may be bound at any given time. + fn bind_wl_display(&mut self, display: &wayland_server::Display) -> Result<(), EglError>; + + /// Unbinds a previously bound egl display, if existing. + /// + /// *Note*: As a result any previously created egl-based WlBuffers will not be readable anymore. + /// Your compositor will have to deal with existing buffers of *unknown* type. + fn unbind_wl_display(&mut self); + + /// Returns the underlying [`EGLBufferReader`]. + /// + /// The primary use for this is calling [`buffer_dimensions`] or [`buffer_type`]. + /// + /// Returns `None` if no [`Display`] was previously bound to the underlying [`EGLDisplay`] + /// (see [`ImportEgl::bind_wl_display`]). + fn egl_reader(&self) -> Option<&EGLBufferReader>; + /// 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`]) @@ -295,7 +323,6 @@ pub trait ImportEgl: Renderer { fn import_egl_buffer( &mut self, buffer: &wl_buffer::WlBuffer, - egl: &EGLBufferReader, ) -> Result<::TextureId, ::Error>; } @@ -351,12 +378,8 @@ pub trait ImportDma: Renderer { // 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 { +#[cfg(feature = "wayland_frontend")] +pub trait ImportAll: Renderer { /// Import a given buffer into the renderer. /// /// Returns a texture_id, which can be used with [`Frame::render_texture`] (or [`Frame::render_texture_at`]) @@ -380,21 +403,86 @@ pub trait ImportAll: Renderer + ImportShm + ImportEgl { 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, - } - } + ) -> Option::TextureId, ::Error>>; + + /// Returns the *type* of a wl_buffer + /// + /// *Note*: Different to [`buffer_type`] this variant uses its internal `EGLBufferReader`, if + /// - the underlying Renderer supports `ImportEgl`, + /// - smithay was compiled with the `backend_egl` and `use_system_lib`, + /// - and the underlying Renderer bound via [`ImportEgl::bind_wl_display`] successfully. + /// + /// Returns `None` if the type is not known to smithay + /// or otherwise not supported (e.g. not initialized using one of smithays [`crate::wayland`]-handlers). + fn buffer_type(&self, buffer: &wl_buffer::WlBuffer) -> Option; + + /// Returns the dimensions of a wl_buffer + /// + /// *Note*: This will only return dimensions for buffer types known to smithay (see [`buffer_type`]). + /// + /// *Note*: Different to [`buffer_type`] this variant uses its internal `EGLBufferReader`, if + /// - the underlying Renderer supports `ImportEgl`, + /// - smithay was compiled with the `backend_egl` and `use_system_lib`, + /// - and the underlying Renderer bound via [`ImportEgl::bind_wl_display`] successfully. + fn buffer_dimensions(&self, buffer: &wl_buffer::WlBuffer) -> Option<(i32, i32)>; } + +// TODO: Do this with specialization, when possible and do default implementations #[cfg(all( feature = "wayland_frontend", feature = "backend_egl", feature = "use_system_lib" ))] -impl ImportAll for R {} +impl ImportAll for R { + fn import_buffer( + &mut self, + buffer: &wl_buffer::WlBuffer, + surface: Option<&SurfaceAttributes>, + damage: &[Rectangle], + ) -> Option::TextureId, ::Error>> { + match buffer_type(buffer, self.egl_reader()) { + Some(BufferType::Shm) => Some(self.import_shm_buffer(buffer, surface, damage)), + Some(BufferType::Egl) => Some(self.import_egl_buffer(buffer)), + Some(BufferType::Dma) => Some(self.import_dma_buffer(buffer)), + _ => None, + } + } + + fn buffer_type(&self, buffer: &wl_buffer::WlBuffer) -> Option { + buffer_type(buffer, self.egl_reader()) + } + + fn buffer_dimensions(&self, buffer: &wl_buffer::WlBuffer) -> Option<(i32, i32)> { + buffer_dimensions(buffer, self.egl_reader()) + } +} + +#[cfg(all( + feature = "wayland_frontend", + not(all(feature = "backend_egl", feature = "use_system_lib")) +))] +impl ImportAll for R { + fn import_buffer( + &mut self, + buffer: &wl_buffer::WlBuffer, + surface: Option<&SurfaceAttributes>, + damage: &[Rectangle], + ) -> Option::TextureId, ::Error>> { + match buffer_type(buffer) { + Some(BufferType::Shm) => Some(self.import_shm_buffer(buffer, surface, damage)), + Some(BufferType::Dma) => Some(self.import_dma_buffer(buffer)), + _ => None, + } + } + + fn buffer_type(&self, buffer: &wl_buffer::WlBuffer) -> Option { + buffer_type(buffer) + } + + fn buffer_dimensions(&self, buffer: &wl_buffer::WlBuffer) -> Option<(i32, i32)> { + buffer_dimensions(buffer) + } +} #[cfg(feature = "wayland_frontend")] #[non_exhaustive]