From 66f198ffd1d07839443bc6166cb975a117fcab24 Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld <github@drakulix.de> Date: Tue, 14 Jan 2025 19:22:59 +0100 Subject: [PATCH] renderer: Introduce explicit framebuffers --- Cargo.toml | 1 + anvil/src/drawing.rs | 6 +- anvil/src/render.rs | 5 +- anvil/src/shell/element.rs | 2 +- anvil/src/udev.rs | 2 +- anvil/src/winit.rs | 49 +- anvil/src/x11.rs | 16 +- examples/buffer_test.rs | 29 +- examples/minimal.rs | 76 +-- smallvil/src/winit.rs | 32 +- src/backend/drm/compositor/elements.rs | 8 +- src/backend/drm/compositor/frame_result.rs | 25 +- src/backend/drm/compositor/mod.rs | 34 +- src/backend/drm/output.rs | 44 +- src/backend/renderer/damage/mod.rs | 414 +++++-------- src/backend/renderer/element/memory.rs | 135 +---- src/backend/renderer/element/mod.rs | 140 +---- src/backend/renderer/element/solid.rs | 116 +--- src/backend/renderer/element/surface.rs | 183 +----- src/backend/renderer/element/tests.rs | 24 +- src/backend/renderer/element/texture.rs | 236 +------- .../renderer/element/utils/elements.rs | 12 +- src/backend/renderer/gles/element.rs | 4 +- src/backend/renderer/gles/mod.rs | 509 +++++++--------- src/backend/renderer/gles/texture.rs | 4 +- src/backend/renderer/glow.rs | 95 ++- src/backend/renderer/mod.rs | 135 ++--- src/backend/renderer/multigpu/gbm.rs | 21 +- src/backend/renderer/multigpu/mod.rs | 542 +++++++++++------- src/backend/renderer/pixman/mod.rs | 171 +++--- src/backend/renderer/test.rs | 57 +- src/backend/renderer/utils/wayland.rs | 24 +- src/backend/winit/mod.rs | 42 +- src/desktop/space/element/mod.rs | 2 +- src/desktop/space/element/wayland.rs | 2 +- src/desktop/space/mod.rs | 11 +- src/desktop/space/wayland/layer.rs | 2 +- src/desktop/space/wayland/window.rs | 2 +- src/desktop/space/wayland/x11.rs | 2 +- wlcs_anvil/src/main_loop.rs | 10 +- 40 files changed, 1222 insertions(+), 2002 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ea2d574e2dc3..03aff340f573 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,6 +69,7 @@ encoding_rs = { version = "0.8.33", optional = true } profiling = "1.0.13" smallvec = "1.11" pixman = { version = "0.2.1", features = ["drm-fourcc", "sync"], optional = true } +aliasable = "0.1.3" [dev-dependencies] diff --git a/anvil/src/drawing.rs b/anvil/src/drawing.rs index 1f43faa36934..4cb028e2f509 100644 --- a/anvil/src/drawing.rs +++ b/anvil/src/drawing.rs @@ -191,14 +191,14 @@ where } #[cfg(feature = "debug")] -impl<R> RenderElement<R> for FpsElement<<R as Renderer>::TextureId> +impl<R> RenderElement<R> for FpsElement<R::TextureId> where R: Renderer + ImportAll, - <R as Renderer>::TextureId: 'static, + R::TextureId: 'static, { fn draw( &self, - frame: &mut <R as Renderer>::Frame<'_>, + frame: &mut R::Frame<'_, '_>, _src: Rectangle<f64, Buffer>, dst: Rectangle<i32, Physical>, damage: &[Rectangle<i32, Physical>], diff --git a/anvil/src/render.rs b/anvil/src/render.rs index 843cea19af93..54905e1a2c03 100644 --- a/anvil/src/render.rs +++ b/anvil/src/render.rs @@ -35,7 +35,7 @@ smithay::backend::renderer::element::render_elements! { // a feature-dependent lifetime, which introduces a lot more feature bounds // as the whole type changes and we can't have an unused lifetime (for when "debug" is disabled) // in the declaration. - Fps=FpsElement<<R as Renderer>::TextureId>, + Fps=FpsElement<R::TextureId>, } impl<R: Renderer> std::fmt::Debug for CustomRenderElements<R> { @@ -195,6 +195,7 @@ pub fn render_output<'a, 'd, R>( space: &'a Space<WindowElement>, custom_elements: impl IntoIterator<Item = CustomRenderElements<R>>, renderer: &'a mut R, + framebuffer: &'a mut R::Framebuffer<'_>, damage_tracker: &'d mut OutputDamageTracker, age: usize, show_window_preview: bool, @@ -205,5 +206,5 @@ where { let (elements, clear_color) = output_elements(output, space, custom_elements, renderer, show_window_preview); - damage_tracker.render_output(renderer, age, &elements, clear_color) + damage_tracker.render_output(renderer, framebuffer, age, &elements, clear_color) } diff --git a/anvil/src/shell/element.rs b/anvil/src/shell/element.rs index 50af3781bea8..6ae0f4836518 100644 --- a/anvil/src/shell/element.rs +++ b/anvil/src/shell/element.rs @@ -416,7 +416,7 @@ impl<R: Renderer> std::fmt::Debug for WindowRenderElement<R> { impl<R> AsRenderElements<R> for WindowElement where R: Renderer + ImportAll + ImportMem, - <R as Renderer>::TextureId: Clone + Texture + 'static, + R::TextureId: Clone + Texture + 'static, { type RenderElement = WindowRenderElement<R>; diff --git a/anvil/src/udev.rs b/anvil/src/udev.rs index 75ff68d2cd61..33d86dcc291d 100644 --- a/anvil/src/udev.rs +++ b/anvil/src/udev.rs @@ -1354,7 +1354,7 @@ impl AnvilState<UdevData> { !has_rendered } Err(err) => { - warn!("Error during rendering: {:?}", err); + warn!("Error during rendering: {:#?}", err); match err { SwapBuffersError::AlreadySwapped => false, SwapBuffersError::TemporaryFailure(err) => match err.downcast_ref::<DrmError>() { diff --git a/anvil/src/winit.rs b/anvil/src/winit.rs index 66fb0caaf628..6a526ac31879 100644 --- a/anvil/src/winit.rs +++ b/anvil/src/winit.rs @@ -291,31 +291,29 @@ pub fn run_winit() { #[cfg(feature = "debug")] let mut renderdoc = state.renderdoc.as_mut(); - let render_res = backend.bind().and_then(|_| { + + let age = if *full_redraw > 0 { + 0 + } else { + backend.buffer_age().unwrap_or(0) + }; + #[cfg(feature = "debug")] + let window_handle = backend + .window() + .window_handle() + .map(|handle| { + if let RawWindowHandle::Wayland(handle) = handle.as_raw() { + handle.surface.as_ptr() + } else { + std::ptr::null_mut() + } + }) + .unwrap_or_else(|_| std::ptr::null_mut()); + let render_res = backend.bind().and_then(|(renderer, mut fb)| { #[cfg(feature = "debug")] if let Some(renderdoc) = renderdoc.as_mut() { - renderdoc.start_frame_capture( - backend.renderer().egl_context().get_context_handle(), - backend - .window() - .window_handle() - .map(|handle| { - if let RawWindowHandle::Wayland(handle) = handle.as_raw() { - handle.surface.as_ptr() - } else { - std::ptr::null_mut() - } - }) - .unwrap_or_else(|_| std::ptr::null_mut()), - ); + renderdoc.start_frame_capture(renderer.egl_context().get_context_handle(), window_handle); } - let age = if *full_redraw > 0 { - 0 - } else { - backend.buffer_age().unwrap_or(0) - }; - - let renderer = backend.renderer(); let mut elements = Vec::<CustomRenderElements<GlesRenderer>>::new(); @@ -349,11 +347,12 @@ pub fn run_winit() { #[cfg(feature = "debug")] elements.push(CustomRenderElements::Fps(fps_element.clone())); - render_output( + let res = render_output( &output, space, elements, renderer, + &mut fb, damage_tracker, age, show_window_preview, @@ -361,7 +360,9 @@ pub fn run_winit() { .map_err(|err| match err { OutputDamageTrackerError::Rendering(err) => err.into(), _ => unreachable!(), - }) + }); + + res }); match render_res { diff --git a/anvil/src/x11.rs b/anvil/src/x11.rs index 88803754f820..154f6102f964 100644 --- a/anvil/src/x11.rs +++ b/anvil/src/x11.rs @@ -314,12 +314,15 @@ pub fn run_x11() { #[cfg(feature = "debug")] fps_element.update_fps(fps); - let (buffer, age) = backend_data.surface.buffer().expect("gbm device was destroyed"); - if let Err(err) = backend_data.renderer.bind(buffer) { - error!("Error while binding buffer: {}", err); - profiling::finish_frame!(); - continue; - } + let (mut buffer, age) = backend_data.surface.buffer().expect("gbm device was destroyed"); + let mut fb = match backend_data.renderer.bind(&mut buffer) { + Ok(fb) => fb, + Err(err) => { + error!("Error while binding buffer: {}", err); + profiling::finish_frame!(); + continue; + } + }; #[cfg(feature = "debug")] if let Some(renderdoc) = state.renderdoc.as_mut() { @@ -394,6 +397,7 @@ pub fn run_x11() { &state.space, elements, &mut backend_data.renderer, + &mut fb, &mut backend_data.damage_tracker, age.into(), state.show_window_preview, diff --git a/examples/buffer_test.rs b/examples/buffer_test.rs index 26c2cefd1801..034c64ba84b2 100644 --- a/examples/buffer_test.rs +++ b/examples/buffer_test.rs @@ -202,7 +202,7 @@ fn buffer_test(args: TestArgs) { }; // 2. alloc buffer - let buffer = allocator + let mut buffer = allocator .create_buffer(args.width, args.height, args.fourcc, &[args.modifier]) .expect("Failed to allocate buffer"); @@ -223,12 +223,7 @@ fn buffer_test(args: TestArgs) { let context = EGLContext::new(&display).expect("Failed to create EGL context"); let mut renderer = unsafe { GlesRenderer::new(context).expect("Failed to init GL ES renderer") }; - render_into( - &mut renderer, - buffer.clone(), - args.width as i32, - args.height as i32, - ); + render_into(&mut renderer, &mut buffer, args.width as i32, args.height as i32); } } @@ -274,15 +269,15 @@ fn buffer_test(args: TestArgs) { } } -fn render_into<R, T>(renderer: &mut R, buffer: T, w: i32, h: i32) +fn render_into<R, T>(renderer: &mut R, buffer: &mut T, w: i32, h: i32) where R: Renderer + Bind<T>, { // Bind it as a framebuffer - renderer.bind(buffer).expect("Failed to bind dmabuf"); + let mut framebuffer = renderer.bind(buffer).expect("Failed to bind dmabuf"); let mut frame = renderer - .render((w, h).into(), Transform::Normal) + .render(&mut framebuffer, (w, h).into(), Transform::Normal) .expect("Failed to create render frame"); frame .clear( @@ -322,11 +317,13 @@ where let texture = renderer .import_dmabuf(&buffer, None) .expect("Failed to import dmabuf"); - let offscreen = Offscreen::<T>::create_buffer(renderer, Fourcc::Abgr8888, (w, h).into()) + let mut offscreen = Offscreen::<T>::create_buffer(renderer, Fourcc::Abgr8888, (w, h).into()) .expect("Failed to create offscreen buffer"); - renderer.bind(offscreen).expect("Failed to bind offscreen buffer"); + let mut framebuffer = renderer + .bind(&mut offscreen) + .expect("Failed to bind offscreen buffer"); let mut frame = renderer - .render((w, h).into(), Transform::Normal) + .render(&mut framebuffer, (w, h).into(), Transform::Normal) .expect("Failed to create render frame"); frame .render_texture_at( @@ -348,7 +345,11 @@ where if let Some(path) = dump { let mapping = renderer - .copy_framebuffer(Rectangle::from_size((w, h).into()), Fourcc::Abgr8888) + .copy_framebuffer( + &framebuffer, + Rectangle::from_size((w, h).into()), + Fourcc::Abgr8888, + ) .expect("Failed to map framebuffer"); let copy = renderer.map_texture(&mapping).expect("Failed to read mapping"); image::save_buffer(path, copy, w as u32, h as u32, image::ColorType::Rgba8) diff --git a/examples/minimal.rs b/examples/minimal.rs index 80021d6a400d..310a66d8753e 100644 --- a/examples/minimal.rs +++ b/examples/minimal.rs @@ -205,49 +205,51 @@ pub fn run_winit() -> Result<(), Box<dyn std::error::Error>> { PumpStatus::Exit(_) => return Ok(()), }; - backend.bind().unwrap(); - let size = backend.window_size(); let damage = Rectangle::from_size(size); + { + let (renderer, mut framebuffer) = backend.bind().unwrap(); + let elements = state + .xdg_shell_state + .toplevel_surfaces() + .iter() + .flat_map(|surface| { + render_elements_from_surface_tree( + renderer, + surface.wl_surface(), + (0, 0), + 1.0, + 1.0, + Kind::Unspecified, + ) + }) + .collect::<Vec<WaylandSurfaceRenderElement<GlesRenderer>>>(); + + let mut frame = renderer + .render(&mut framebuffer, size, Transform::Flipped180) + .unwrap(); + frame.clear(Color32F::new(0.1, 0.0, 0.0, 1.0), &[damage]).unwrap(); + draw_render_elements(&mut frame, 1.0, &elements, &[damage]).unwrap(); + // We rely on the nested compositor to do the sync for us + let _ = frame.finish().unwrap(); - let elements = state - .xdg_shell_state - .toplevel_surfaces() - .iter() - .flat_map(|surface| { - render_elements_from_surface_tree( - backend.renderer(), - surface.wl_surface(), - (0, 0), - 1.0, - 1.0, - Kind::Unspecified, - ) - }) - .collect::<Vec<WaylandSurfaceRenderElement<GlesRenderer>>>(); - - let mut frame = backend.renderer().render(size, Transform::Flipped180).unwrap(); - frame.clear(Color32F::new(0.1, 0.0, 0.0, 1.0), &[damage]).unwrap(); - draw_render_elements(&mut frame, 1.0, &elements, &[damage]).unwrap(); - // We rely on the nested compositor to do the sync for us - let _ = frame.finish().unwrap(); - - for surface in state.xdg_shell_state.toplevel_surfaces() { - send_frames_surface_tree(surface.wl_surface(), start_time.elapsed().as_millis() as u32); - } + for surface in state.xdg_shell_state.toplevel_surfaces() { + send_frames_surface_tree(surface.wl_surface(), start_time.elapsed().as_millis() as u32); + } - if let Some(stream) = listener.accept()? { - println!("Got a client: {:?}", stream); + if let Some(stream) = listener.accept()? { + println!("Got a client: {:?}", stream); - let client = display - .handle() - .insert_client(stream, Arc::new(ClientState::default())) - .unwrap(); - clients.push(client); - } + let client = display + .handle() + .insert_client(stream, Arc::new(ClientState::default())) + .unwrap(); + clients.push(client); + } - display.dispatch_clients(&mut state)?; - display.flush_clients()?; + display.dispatch_clients(&mut state)?; + display.flush_clients()?; + } // It is important that all events on the display have been dispatched and flushed to clients before // swapping buffers because this operation may block. diff --git a/smallvil/src/winit.rs b/smallvil/src/winit.rs index 782b6ee7d3c9..98e94ef8d316 100644 --- a/smallvil/src/winit.rs +++ b/smallvil/src/winit.rs @@ -68,18 +68,26 @@ pub fn init_winit( let size = backend.window_size(); let damage = Rectangle::from_size(size); - backend.bind().unwrap(); - smithay::desktop::space::render_output::<_, WaylandSurfaceRenderElement<GlesRenderer>, _, _>( - &output, - backend.renderer(), - 1.0, - 0, - [&state.space], - &[], - &mut damage_tracker, - [0.1, 0.1, 0.1, 1.0], - ) - .unwrap(); + { + let (renderer, mut framebuffer) = backend.bind().unwrap(); + smithay::desktop::space::render_output::< + _, + WaylandSurfaceRenderElement<GlesRenderer>, + _, + _, + >( + &output, + renderer, + &mut framebuffer, + 1.0, + 0, + [&state.space], + &[], + &mut damage_tracker, + [0.1, 0.1, 0.1, 1.0], + ) + .unwrap(); + } backend.submit(Some(&[damage])).unwrap(); state.space.elements().for_each(|window| { diff --git a/src/backend/drm/compositor/elements.rs b/src/backend/drm/compositor/elements.rs index 36fba72ef782..d0c793854d1d 100644 --- a/src/backend/drm/compositor/elements.rs +++ b/src/backend/drm/compositor/elements.rs @@ -39,12 +39,12 @@ where { fn draw( &self, - frame: &mut <R as Renderer>::Frame<'_>, + frame: &mut R::Frame<'_, '_>, _src: Rectangle<f64, Buffer>, dst: Rectangle<i32, Physical>, damage: &[Rectangle<i32, Physical>], _opaque_regions: &[Rectangle<i32, Physical>], - ) -> Result<(), <R as Renderer>::Error> { + ) -> Result<(), R::Error> { frame.clear( Color32F::TRANSPARENT, &damage @@ -172,12 +172,12 @@ where { fn draw( &self, - _frame: &mut <R as Renderer>::Frame<'_>, + _frame: &mut R::Frame<'_, '_>, _src: Rectangle<f64, Buffer>, _dst: Rectangle<i32, Physical>, _damage: &[Rectangle<i32, Physical>], _opaque_regions: &[Rectangle<i32, Physical>], - ) -> Result<(), <R as Renderer>::Error> { + ) -> Result<(), R::Error> { // We do not actually draw anything here Ok(()) } diff --git a/src/backend/drm/compositor/frame_result.rs b/src/backend/drm/compositor/frame_result.rs index 7c0cfdf898e9..2ca9a11824a6 100644 --- a/src/backend/drm/compositor/frame_result.rs +++ b/src/backend/drm/compositor/frame_result.rs @@ -12,7 +12,7 @@ use crate::{ element::{Element, Id, RenderElement, RenderElementStates}, sync::SyncPoint, utils::{CommitCounter, DamageSet, DamageSnapshot, OpaqueRegions}, - Blit, Color32F, Frame, Renderer, + Bind, Blit, Color32F, Frame, Renderer, }, }, output::OutputNoMode, @@ -261,7 +261,7 @@ where <B as AsDmabuf>::Error: std::fmt::Debug, F: Framebuffer, { - /// Blit the frame result into a currently bound buffer + /// Blit the frame result #[allow(clippy::too_many_arguments)] pub fn blit_frame_result<R>( &self, @@ -269,12 +269,13 @@ where transform: Transform, scale: impl Into<Scale<f64>>, renderer: &mut R, + framebuffer: &mut R::Framebuffer<'_>, damage: impl IntoIterator<Item = Rectangle<i32, Physical>>, filter: impl IntoIterator<Item = Id>, - ) -> Result<SyncPoint, BlitFrameResultError<<R as Renderer>::Error, <B as AsDmabuf>::Error>> + ) -> Result<SyncPoint, BlitFrameResultError<R::Error, <B as AsDmabuf>::Error>> where - R: Renderer + Blit<Dmabuf>, - <R as Renderer>::TextureId: 'static, + R: Renderer + Bind<Dmabuf> + Blit, + R::TextureId: 'static, E: Element + RenderElement<R>, { let size = size.into(); @@ -335,7 +336,7 @@ where tracing::trace!("clearing frame damage {:#?}", clear_damage); let mut frame = renderer - .render(size, transform) + .render(framebuffer, size, transform) .map_err(BlitFrameResultError::Rendering)?; frame @@ -346,7 +347,7 @@ where } // first do the potential blit - if let Some((sync, dmabuf, geometry)) = primary_dmabuf { + if let Some((sync, mut dmabuf, geometry)) = primary_dmabuf { let blit_damage = damage .iter() .filter_map(|d| d.intersection(geometry)) @@ -355,10 +356,14 @@ where tracing::trace!("blitting frame with damage: {:#?}", blit_damage); renderer.wait(&sync).map_err(BlitFrameResultError::Rendering)?; + let fb = renderer + .bind(&mut dmabuf) + .map_err(BlitFrameResultError::Rendering)?; for rect in blit_damage { renderer - .blit_from( - dmabuf.clone(), + .blit( + &fb, + framebuffer, rect, rect, crate::backend::renderer::TextureFilter::Linear, @@ -372,7 +377,7 @@ where tracing::trace!("drawing {} frame element(s)", elements_to_render.len()); let mut frame = renderer - .render(size, transform) + .render(framebuffer, size, transform) .map_err(BlitFrameResultError::Rendering)?; for element in elements_to_render.iter().rev() { diff --git a/src/backend/drm/compositor/mod.rs b/src/backend/drm/compositor/mod.rs index 493a96a83520..66a0a2136157 100644 --- a/src/backend/drm/compositor/mod.rs +++ b/src/backend/drm/compositor/mod.rs @@ -140,8 +140,8 @@ use wayland_server::{protocol::wl_buffer::WlBuffer, Resource}; #[cfg(feature = "renderer_pixman")] use crate::backend::renderer::{ - pixman::{PixmanError, PixmanRenderBuffer, PixmanRenderer, PixmanTexture}, - Frame as _, ImportAll, Unbind, + pixman::{PixmanError, PixmanRenderer, PixmanTexture}, + ImportAll, }; use crate::{ backend::{ @@ -161,7 +161,7 @@ use crate::{ }, sync::SyncPoint, utils::{CommitCounter, DamageBag}, - Bind, Color32F, DebugFlags, Renderer, Texture, + Bind, Color32F, DebugFlags, Frame as RendererFrame, Renderer, RendererSuper, Texture, }, SwapBuffersError, }, @@ -832,7 +832,7 @@ pub(crate) type RenderFrameErrorType<A, F, R> = RenderFrameError< <A as Allocator>::Error, <<A as Allocator>::Buffer as AsDmabuf>::Error, <F as ExportFramebuffer<<A as Allocator>::Buffer>>::Error, - <R as Renderer>::Error, + <R as RendererSuper>::Error, >; #[derive(Debug)] @@ -1684,8 +1684,7 @@ where where E: RenderElement<R>, R: Renderer + Bind<Dmabuf>, - <R as Renderer>::TextureId: Texture + 'static, - <R as Renderer>::Error: Send + Sync + 'static, + R::TextureId: Texture + 'static, { let mut clear_color = clear_color.into(); @@ -2165,7 +2164,7 @@ where primary_plane_elements.len(), self.surface.plane(), ); - let (dmabuf, age) = { + let (mut dmabuf, age) = { let primary_plane_state = next_frame_state.plane_state(self.surface.plane()).unwrap(); let config = primary_plane_state.config.as_ref().unwrap(); let slot = match &config.buffer.buffer { @@ -2230,9 +2229,12 @@ where ) .collect::<Vec<_>>(); + let mut framebuffer = renderer + .bind(&mut dmabuf) + .map_err(|err| RenderFrameError::RenderFrame(OutputDamageTrackerError::Rendering(err)))?; let render_res = self.damage_tracker - .render_output_with(renderer, dmabuf, age, &elements, clear_color); + .render_output(renderer, &mut framebuffer, age, &elements, clear_color); // restore the renderer debug flags renderer.set_debug_flags(renderer_debug_flags); @@ -3297,14 +3299,14 @@ where }?; let ret = cursor_buffer - .map_mut::<_, Result<_, <PixmanRenderer as Renderer>::Error>>( + .map_mut::<_, Result<_, PixmanError>>( 0, 0, cursor_buffer_size.w as u32, cursor_buffer_size.h as u32, |mbo| { let plane_pixman_format = pixman::FormatCode::try_from(DrmFourcc::Argb8888).unwrap(); - let cursor_dst = unsafe { + let mut cursor_dst = unsafe { pixman::Image::from_raw_mut( plane_pixman_format, mbo.width() as usize, @@ -3315,9 +3317,9 @@ where ) } .map_err(|_| PixmanError::ImportFailed)?; - pixman_renderer.bind(PixmanRenderBuffer::from(cursor_dst))?; - - let mut frame = pixman_renderer.render(cursor_plane_size, output_transform)?; + let mut framebuffer = pixman_renderer.bind(&mut cursor_dst)?; + let mut frame = + pixman_renderer.render(&mut framebuffer, cursor_plane_size, output_transform)?; frame.clear(Color32F::TRANSPARENT, &[Rectangle::from_size(cursor_plane_size)])?; let src = element.src(); let dst = Rectangle::from_size(element_geometry.size); @@ -3336,8 +3338,6 @@ where ) .expect("Lost track of cursor device"); - _ = pixman_renderer.unbind(); - if let Err(err) = ret { debug!("{err}"); return None; @@ -4343,7 +4343,7 @@ pub enum RenderFrameError< A: std::error::Error + Send + Sync + 'static, B: std::error::Error + Send + Sync + 'static, F: std::error::Error + Send + Sync + 'static, - R: std::error::Error + Send + Sync + 'static, + R: std::error::Error, > { /// Preparing the frame encountered an error #[error(transparent)] @@ -4358,7 +4358,7 @@ where A: std::error::Error + Send + Sync + 'static, B: std::error::Error + Send + Sync + 'static, F: std::error::Error + Send + Sync + 'static, - R: std::error::Error + Send + Sync + 'static, + R: std::error::Error, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { diff --git a/src/backend/drm/output.rs b/src/backend/drm/output.rs index 43725c4bd67a..4054ed483cb4 100644 --- a/src/backend/drm/output.rs +++ b/src/backend/drm/output.rs @@ -18,7 +18,7 @@ use crate::{ gbm::GbmDevice, Allocator, }, - renderer::{element::RenderElement, Bind, Color32F, DebugFlags, Renderer, Texture}, + renderer::{element::RenderElement, Bind, Color32F, DebugFlags, Renderer, RendererSuper, Texture}, }, output::OutputModeSource, }; @@ -142,7 +142,7 @@ pub type DrmOutputManagerResult<U, A, F, R> = Result< <A as Allocator>::Error, <<A as Allocator>::Buffer as AsDmabuf>::Error, <F as ExportFramebuffer<<A as Allocator>::Buffer>>::Error, - <R as Renderer>::Error, + <R as RendererSuper>::Error, >, >; @@ -224,8 +224,8 @@ where where E: RenderElement<R>, R: Renderer + Bind<Dmabuf>, - <R as Renderer>::TextureId: Texture + 'static, - <R as Renderer>::Error: Send + Sync + 'static, + R::TextureId: Texture + 'static, + R::Error: Send + Sync + 'static, { let output_mode_source = output_mode_source.into(); @@ -420,8 +420,8 @@ where where E: RenderElement<R>, R: Renderer + Bind<Dmabuf>, - <R as Renderer>::TextureId: Texture + 'static, - <R as Renderer>::Error: Send + Sync + 'static, + R::TextureId: Texture + 'static, + R::Error: Send + Sync + 'static, { use_mode_internal( &self.compositor, @@ -449,8 +449,8 @@ where where E: RenderElement<R>, R: Renderer + Bind<Dmabuf>, - <R as Renderer>::TextureId: Texture + 'static, - <R as Renderer>::Error: Send + Sync + 'static, + R::TextureId: Texture + 'static, + R::Error: Send + Sync + 'static, { let mut write_guard = self.compositor.write().unwrap(); @@ -604,8 +604,8 @@ where where E: RenderElement<R>, R: Renderer + Bind<Dmabuf>, - <R as Renderer>::TextureId: Texture + 'static, - <R as Renderer>::Error: Send + Sync + 'static, + R::TextureId: Texture + 'static, + R::Error: Send + Sync + 'static, { self.with_compositor(|compositor| { compositor.render_frame(renderer, elements, clear_color, frame_mode) @@ -666,8 +666,8 @@ where where E: RenderElement<R>, R: Renderer + Bind<Dmabuf>, - <R as Renderer>::TextureId: Texture + 'static, - <R as Renderer>::Error: Send + Sync + 'static, + R::TextureId: Texture + 'static, + R::Error: Send + Sync + 'static, { use_mode_internal( &self.compositor, @@ -740,8 +740,8 @@ where U: 'static, E: RenderElement<R>, R: Renderer + Bind<Dmabuf>, - <R as Renderer>::TextureId: Texture + 'static, - <R as Renderer>::Error: Send + Sync + 'static, + R::TextureId: Texture + 'static, + R::Error: Send + Sync + 'static, { let mut write_guard = compositor.write().unwrap(); @@ -833,8 +833,8 @@ pub struct DrmOutputRenderElements<R, E> where E: RenderElement<R>, R: Renderer + Bind<Dmabuf>, - <R as Renderer>::TextureId: Texture + 'static, - <R as Renderer>::Error: Send + Sync + 'static, + R::TextureId: Texture + 'static, + R::Error: Send + Sync + 'static, { render_elements: HashMap<crtc::Handle, (Vec<E>, Color32F)>, _renderer: PhantomData<R>, @@ -844,8 +844,8 @@ impl<R, E> DrmOutputRenderElements<R, E> where E: RenderElement<R>, R: Renderer + Bind<Dmabuf>, - <R as Renderer>::TextureId: Texture + 'static, - <R as Renderer>::Error: Send + Sync + 'static, + R::TextureId: Texture + 'static, + R::Error: Send + Sync + 'static, { /// Construct a new empty set of render elements pub fn new() -> Self { @@ -869,8 +869,8 @@ impl<R, E> Default for DrmOutputRenderElements<R, E> where E: RenderElement<R>, R: Renderer + Bind<Dmabuf>, - <R as Renderer>::TextureId: Texture + 'static, - <R as Renderer>::Error: Send + Sync + 'static, + R::TextureId: Texture + 'static, + R::Error: Send + Sync + 'static, { fn default() -> Self { Self::new() @@ -881,8 +881,8 @@ impl<R, E> DrmOutputRenderElements<R, E> where E: RenderElement<R>, R: Renderer + Bind<Dmabuf>, - <R as Renderer>::TextureId: Texture + 'static, - <R as Renderer>::Error: Send + Sync + 'static, + R::TextureId: Texture + 'static, + R::Error: Send + Sync + 'static, { /// Adds elements to be used when rendering for a given `crtc`. /// diff --git a/src/backend/renderer/damage/mod.rs b/src/backend/renderer/damage/mod.rs index 7267823322e3..f7f4b3f00929 100644 --- a/src/backend/renderer/damage/mod.rs +++ b/src/backend/renderer/damage/mod.rs @@ -27,114 +27,9 @@ //! //! ```no_run //! # use smithay::{ -//! # backend::renderer::{Color32F, DebugFlags, Frame, ImportMem, Renderer, Texture, TextureFilter, sync::SyncPoint}, +//! # backend::renderer::{Color32F, DebugFlags, Frame, ImportMem, Renderer, Texture, TextureFilter, sync::SyncPoint, test::{DummyRenderer, DummyFramebuffer}}, //! # utils::{Buffer, Physical, Rectangle, Size}, //! # }; -//! # -//! # #[derive(Clone, Debug)] -//! # struct FakeTexture; -//! # -//! # impl Texture for FakeTexture { -//! # fn width(&self) -> u32 { -//! # unimplemented!() -//! # } -//! # fn height(&self) -> u32 { -//! # unimplemented!() -//! # } -//! # fn format(&self) -> Option<Fourcc> { -//! # unimplemented!() -//! # } -//! # } -//! # -//! # struct FakeFrame; -//! # -//! # impl Frame for FakeFrame { -//! # type Error = std::convert::Infallible; -//! # type TextureId = FakeTexture; -//! # -//! # fn id(&self) -> usize { unimplemented!() } -//! # fn clear(&mut self, _: Color32F, _: &[Rectangle<i32, Physical>]) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn draw_solid( -//! # &mut self, -//! # _dst: Rectangle<i32, Physical>, -//! # _damage: &[Rectangle<i32, Physical>], -//! # _color: Color32F, -//! # ) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn render_texture_from_to( -//! # &mut self, -//! # _: &Self::TextureId, -//! # _: Rectangle<f64, Buffer>, -//! # _: Rectangle<i32, Physical>, -//! # _: &[Rectangle<i32, Physical>], -//! # _: &[Rectangle<i32, Physical>], -//! # _: Transform, -//! # _: f32, -//! # ) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn transformation(&self) -> Transform { -//! # unimplemented!() -//! # } -//! # fn finish(self) -> Result<SyncPoint, Self::Error> { unimplemented!() } -//! # fn wait(&mut self, sync: &SyncPoint) -> Result<(), Self::Error> { unimplemented!() } -//! # } -//! # -//! # #[derive(Debug)] -//! # struct FakeRenderer; -//! # -//! # impl Renderer for FakeRenderer { -//! # type Error = std::convert::Infallible; -//! # type TextureId = FakeTexture; -//! # type Frame<'a> = FakeFrame; -//! # -//! # fn id(&self) -> usize { -//! # unimplemented!() -//! # } -//! # fn downscale_filter(&mut self, _: TextureFilter) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn upscale_filter(&mut self, _: TextureFilter) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn set_debug_flags(&mut self, _: DebugFlags) { -//! # unimplemented!() -//! # } -//! # fn debug_flags(&self) -> DebugFlags { -//! # unimplemented!() -//! # } -//! # fn render(&mut self, _: Size<i32, Physical>, _: Transform) -> Result<Self::Frame<'_>, Self::Error> -//! # { -//! # unimplemented!() -//! # } -//! # fn wait(&mut self, sync: &SyncPoint) -> Result<(), Self::Error> { unimplemented!() } -//! # } -//! # -//! # impl ImportMem for FakeRenderer { -//! # fn import_memory( -//! # &mut self, -//! # _: &[u8], -//! # _: Fourcc, -//! # _: Size<i32, Buffer>, -//! # _: bool, -//! # ) -> Result<Self::TextureId, Self::Error> { -//! # unimplemented!() -//! # } -//! # fn update_memory( -//! # &mut self, -//! # _: &Self::TextureId, -//! # _: &[u8], -//! # _: Rectangle<i32, Buffer>, -//! # ) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn mem_formats(&self) -> Box<dyn Iterator<Item=Fourcc>> { -//! # unimplemented!() -//! # } -//! # } //! use smithay::{ //! backend::{ //! allocator::Fourcc, @@ -152,7 +47,8 @@ //! //! const WIDTH: i32 = 10; //! const HEIGHT: i32 = 10; -//! # let mut renderer = FakeRenderer; +//! # let mut renderer = DummyRenderer; +//! # let mut framebuffer = DummyFramebuffer; //! # let buffer_age = 0; //! //! // Initialize a new damage tracker for a static output @@ -188,6 +84,7 @@ //! damage_tracker //! .render_output( //! &mut renderer, +//! &mut framebuffer, //! buffer_age, //! &[render_element], //! [0.8, 0.8, 0.9, 1.0], @@ -215,7 +112,7 @@ use super::{ element::{Element, Id, RenderElement, RenderElementState, RenderElementStates}, sync::SyncPoint, utils::CommitCounter, - Bind, Color32F, + Color32F, }; use super::{Renderer, Texture}; @@ -411,35 +308,15 @@ impl OutputDamageTracker { &self.mode } - /// Render this output with the provided [`Renderer`] in the provided buffer - /// - /// - `elements` for this output in front-to-back order - #[instrument(level = "trace", parent = &self.span, skip(renderer, elements, buffer))] - #[profiling::function] - pub fn render_output_with<E, R, B>( - &mut self, - renderer: &mut R, - buffer: B, - age: usize, - elements: &[E], - clear_color: Color32F, - ) -> Result<RenderOutputResult<'_>, Error<R::Error>> - where - E: RenderElement<R>, - R: Renderer + Bind<B>, - <R as Renderer>::TextureId: Texture, - { - self.render_output_internal(renderer, age, elements, clear_color, |r| r.bind(buffer)) - } - /// Render this output with the provided [`Renderer`] /// /// - `elements` for this output in front-to-back order - #[instrument(level = "trace", parent = &self.span, skip(renderer, elements, clear_color))] + #[instrument(level = "trace", parent = &self.span, skip(renderer, framebuffer, elements, clear_color))] #[profiling::function] pub fn render_output<E, R>( &mut self, renderer: &mut R, + framebuffer: &mut R::Framebuffer<'_>, age: usize, elements: &[E], clear_color: impl Into<Color32F>, @@ -447,9 +324,136 @@ impl OutputDamageTracker { where E: RenderElement<R>, R: Renderer, - <R as Renderer>::TextureId: Texture, + R::TextureId: Texture, { - self.render_output_internal(renderer, age, elements, clear_color.into(), |_| Ok(())) + let clear_color = clear_color.into(); + let (output_size, output_scale, output_transform) = + std::convert::TryInto::<(Size<i32, Physical>, Scale<f64>, Transform)>::try_into(&self.mode)?; + + // Output transform is specified in surface-rotation, so inversion gives us the + // render transform for the output itself. + let output_transform = output_transform.invert(); + + // We have to apply to output transform to the output size so that the intersection + // tests in damage_output_internal produces the correct results and do not crop + // damage with the wrong size + let output_geo = Rectangle::from_size(output_transform.transform_size(output_size)); + + // This will hold all the damage we need for this rendering step + let mut render_elements: Vec<&E> = Vec::with_capacity(elements.len()); + let states = self.damage_output_internal( + age, + elements, + output_scale, + output_transform, + output_geo, + Some(clear_color), + &mut render_elements, + ); + + if self.damage.is_empty() { + trace!("no damage, skipping rendering"); + return Ok(RenderOutputResult::skipped(states)); + } + + trace!( + "rendering with damage {:?} and opaque regions {:?}", + self.damage, + self.opaque_regions + ); + + let render_res = (|| { + // we have to take the element damage to be able to move it around + let mut element_damage = std::mem::take(&mut self.element_damage); + let mut element_opaque_regions = std::mem::take(&mut self.element_opaque_regions); + let mut frame = renderer.render(framebuffer, output_size, output_transform)?; + + element_damage.clear(); + element_damage.extend_from_slice(&self.damage); + element_damage = + Rectangle::subtract_rects_many_in_place(element_damage, self.opaque_regions.iter().copied()); + + trace!("clearing damage {:?}", element_damage); + frame.clear(clear_color, &element_damage)?; + + for (z_index, element) in render_elements.iter().rev().enumerate() { + let element_id = element.id(); + let element_geometry = element.geometry(output_scale); + + element_damage.clear(); + element_damage.extend( + self.damage + .iter() + .filter_map(|d| d.intersection(element_geometry)), + ); + + let element_opaque_regions_range = + self.opaque_regions_index.iter().rev().nth(z_index).unwrap(); + element_damage = Rectangle::subtract_rects_many_in_place( + element_damage, + self.opaque_regions[..element_opaque_regions_range.start] + .iter() + .copied(), + ); + element_damage.iter_mut().for_each(|d| { + d.loc -= element_geometry.loc; + }); + + if element_damage.is_empty() { + trace!( + "skipping rendering element {:?} with geometry {:?}, no damage", + element_id, + element_geometry + ); + continue; + } + + element_opaque_regions.clear(); + element_opaque_regions.extend( + self.opaque_regions[element_opaque_regions_range.start..element_opaque_regions_range.end] + .iter() + .copied() + .map(|mut rect| { + rect.loc -= element_geometry.loc; + rect + }), + ); + + trace!( + "rendering element {:?} with geometry {:?} and damage {:?}", + element_id, + element_geometry, + element_damage, + ); + + element.draw( + &mut frame, + element.src(), + element_geometry, + &element_damage, + &element_opaque_regions, + )?; + } + + // return the element damage so that we can re-use the allocation + std::mem::swap(&mut self.element_damage, &mut element_damage); + std::mem::swap(&mut self.element_opaque_regions, &mut element_opaque_regions); + frame.finish() + })(); + + match render_res { + Ok(sync) => Ok(RenderOutputResult { + sync, + damage: Some(&self.damage), + states, + }), + Err(err) => { + // if the rendering errors on us, we need to be prepared, that this whole buffer was partially updated and thus now unusable. + // thus clean our old states before returning + self.last_state = Default::default(); + Err(Error::Rendering(err)) + } + } } /// Damage this output and return the damage without actually rendering the difference @@ -781,150 +785,4 @@ impl OutputDamageTracker { element_render_states } - - #[profiling::function] - fn render_output_internal<'a, 'e, E, R, F>( - &'a mut self, - renderer: &mut R, - age: usize, - elements: &'e [E], - clear_color: Color32F, - pre_render: F, - ) -> Result<RenderOutputResult<'a>, Error<R::Error>> - where - E: RenderElement<R>, - R: Renderer, - <R as Renderer>::TextureId: Texture, - F: FnOnce(&mut R) -> Result<(), <R as Renderer>::Error>, - { - let (output_size, output_scale, output_transform) = - std::convert::TryInto::<(Size<i32, Physical>, Scale<f64>, Transform)>::try_into(&self.mode)?; - - // Output transform is specified in surface-rotation, so inversion gives us the - // render transform for the output itself. - let output_transform = output_transform.invert(); - - // We have to apply to output transform to the output size so that the intersection - // tests in damage_output_internal produces the correct results and do not crop - // damage with the wrong size - let output_geo = Rectangle::from_size(output_transform.transform_size(output_size)); - - // This will hold all the damage we need for this rendering step - let mut render_elements: Vec<&E> = Vec::with_capacity(elements.len()); - let states = self.damage_output_internal( - age, - elements, - output_scale, - output_transform, - output_geo, - Some(clear_color), - &mut render_elements, - ); - - if self.damage.is_empty() { - trace!("no damage, skipping rendering"); - return Ok(RenderOutputResult::skipped(states)); - } - - trace!( - "rendering with damage {:?} and opaque regions {:?}", - self.damage, - self.opaque_regions - ); - - pre_render(renderer).map_err(Error::Rendering)?; - - let render_res = (|| { - // we have to take the element damage to be able to move it around - let mut element_damage = std::mem::take(&mut self.element_damage); - let mut element_opaque_regions = std::mem::take(&mut self.element_opaque_regions); - let mut frame = renderer.render(output_size, output_transform)?; - - element_damage.clear(); - element_damage.extend_from_slice(&self.damage); - element_damage = - Rectangle::subtract_rects_many_in_place(element_damage, self.opaque_regions.iter().copied()); - - trace!("clearing damage {:?}", element_damage); - frame.clear(clear_color, &element_damage)?; - - for (z_index, element) in render_elements.iter().rev().enumerate() { - let element_id = element.id(); - let element_geometry = element.geometry(output_scale); - - element_damage.clear(); - element_damage.extend( - self.damage - .iter() - .filter_map(|d| d.intersection(element_geometry)), - ); - - let element_opaque_regions_range = - self.opaque_regions_index.iter().rev().nth(z_index).unwrap(); - element_damage = Rectangle::subtract_rects_many_in_place( - element_damage, - self.opaque_regions[..element_opaque_regions_range.start] - .iter() - .copied(), - ); - element_damage.iter_mut().for_each(|d| { - d.loc -= element_geometry.loc; - }); - - if element_damage.is_empty() { - trace!( - "skipping rendering element {:?} with geometry {:?}, no damage", - element_id, - element_geometry - ); - continue; - } - - element_opaque_regions.clear(); - element_opaque_regions.extend( - self.opaque_regions[element_opaque_regions_range.start..element_opaque_regions_range.end] - .iter() - .copied() - .map(|mut rect| { - rect.loc -= element_geometry.loc; - rect - }), - ); - - trace!( - "rendering element {:?} with geometry {:?} and damage {:?}", - element_id, - element_geometry, - element_damage, - ); - - element.draw( - &mut frame, - element.src(), - element_geometry, - &element_damage, - &element_opaque_regions, - )?; - } - - // return the element damage so that we can re-use the allocation - std::mem::swap(&mut self.element_damage, &mut element_damage); - std::mem::swap(&mut self.element_opaque_regions, &mut element_opaque_regions); - frame.finish() - })(); - - match render_res { - Ok(sync) => Ok(RenderOutputResult { - sync, - damage: Some(&self.damage), - states, - }), - Err(err) => { - // if the rendering errors on us, we need to be prepared, that this whole buffer was partially updated and thus now unusable. - // thus clean our old states before returning - self.last_state = Default::default(); - Err(Error::Rendering(err)) - } - } - } } diff --git a/src/backend/renderer/element/memory.rs b/src/backend/renderer/element/memory.rs index 85a48ba2d4c0..af9727065762 100644 --- a/src/backend/renderer/element/memory.rs +++ b/src/backend/renderer/element/memory.rs @@ -6,7 +6,7 @@ //! in the smithay rendering pipeline. As software-rendered elements eventually have to //! upload to the GPU for rendering damage tracking is a crucial part. The [`MemoryRenderBuffer`] //! allows for efficient damage tracking by providing a [`RenderContext`] which accumulates the -//! software-rendering damage. It automatically uploads the damaged parts to a [`Renderer::TextureId`] +//! software-rendering damage. It automatically uploads the damaged parts to a [`RendererSuper::TextureId`](crate::backend::renderer::RendererSuper::TextureId) //! during rendering. //! //! # Why **not** to use this implementation @@ -23,114 +23,9 @@ //! //! ```no_run //! # use smithay::{ -//! # backend::renderer::{Color32F, DebugFlags, Frame, ImportMem, Renderer, Texture, TextureFilter, sync::SyncPoint}, +//! # backend::renderer::{Color32F, DebugFlags, Frame, ImportMem, Renderer, Texture, TextureFilter, sync::SyncPoint, test::{DummyRenderer, DummyFramebuffer}}, //! # utils::{Buffer, Physical}, //! # }; -//! # -//! # #[derive(Clone, Debug)] -//! # struct FakeTexture; -//! # -//! # impl Texture for FakeTexture { -//! # fn width(&self) -> u32 { -//! # unimplemented!() -//! # } -//! # fn height(&self) -> u32 { -//! # unimplemented!() -//! # } -//! # fn format(&self) -> Option<Fourcc> { -//! # unimplemented!() -//! # } -//! # } -//! # -//! # struct FakeFrame; -//! # -//! # impl Frame for FakeFrame { -//! # type Error = std::convert::Infallible; -//! # type TextureId = FakeTexture; -//! # -//! # fn id(&self) -> usize { unimplemented!() } -//! # fn clear(&mut self, _: Color32F, _: &[Rectangle<i32, Physical>]) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn draw_solid( -//! # &mut self, -//! # _dst: Rectangle<i32, Physical>, -//! # _damage: &[Rectangle<i32, Physical>], -//! # _color: Color32F, -//! # ) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn render_texture_from_to( -//! # &mut self, -//! # _: &Self::TextureId, -//! # _: Rectangle<f64, Buffer>, -//! # _: Rectangle<i32, Physical>, -//! # _: &[Rectangle<i32, Physical>], -//! # _: &[Rectangle<i32, Physical>], -//! # _: Transform, -//! # _: f32, -//! # ) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn transformation(&self) -> Transform { -//! # unimplemented!() -//! # } -//! # fn finish(self) -> Result<SyncPoint, Self::Error> { unimplemented!() } -//! # fn wait(&mut self, sync: &SyncPoint) -> Result<(), Self::Error> { unimplemented!() } -//! # } -//! # -//! # #[derive(Debug)] -//! # struct FakeRenderer; -//! # -//! # impl Renderer for FakeRenderer { -//! # type Error = std::convert::Infallible; -//! # type TextureId = FakeTexture; -//! # type Frame<'a> = FakeFrame; -//! # -//! # fn id(&self) -> usize { -//! # unimplemented!() -//! # } -//! # fn downscale_filter(&mut self, _: TextureFilter) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn upscale_filter(&mut self, _: TextureFilter) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn set_debug_flags(&mut self, _: DebugFlags) { -//! # unimplemented!() -//! # } -//! # fn debug_flags(&self) -> DebugFlags { -//! # unimplemented!() -//! # } -//! # fn render(&mut self, _: Size<i32, Physical>, _: Transform) -> Result<Self::Frame<'_>, Self::Error> -//! # { -//! # unimplemented!() -//! # } -//! # fn wait(&mut self, sync: &SyncPoint) -> Result<(), Self::Error> { unimplemented!() } -//! # } -//! # -//! # impl ImportMem for FakeRenderer { -//! # fn import_memory( -//! # &mut self, -//! # _: &[u8], -//! # _: Fourcc, -//! # _: Size<i32, Buffer>, -//! # _: bool, -//! # ) -> Result<Self::TextureId, Self::Error> { -//! # unimplemented!() -//! # } -//! # fn update_memory( -//! # &mut self, -//! # _: &Self::TextureId, -//! # _: &[u8], -//! # _: Rectangle<i32, Buffer>, -//! # ) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn mem_formats(&self) -> Box<dyn Iterator<Item=Fourcc>> { -//! # unimplemented!() -//! # } -//! # } //! use std::time::{Duration, Instant}; //! //! use smithay::{ @@ -176,7 +71,8 @@ //! //! // Initialize a static damage tracker //! let mut damage_tracker = OutputDamageTracker::new((800, 600), 1.0, Transform::Normal); -//! # let mut renderer = FakeRenderer; +//! # let mut renderer = DummyRenderer; +//! # let mut framebuffer = DummyFramebuffer; //! //! let mut last_update = Instant::now(); //! @@ -202,7 +98,7 @@ //! //! // Render the element(s) //! damage_tracker -//! .render_output(&mut renderer, 0, &[&render_element], [0.8, 0.8, 0.9, 1.0]) +//! .render_output(&mut renderer, &mut framebuffer, 0, &[&render_element], [0.8, 0.8, 0.9, 1.0]) //! .expect("failed to render output"); //! } //! ``` @@ -407,15 +303,12 @@ impl MemoryRenderBufferInner { #[instrument(level = "trace", skip(renderer))] #[profiling::function] - fn import_texture<R>( - &mut self, - renderer: &mut R, - ) -> Result<<R as Renderer>::TextureId, <R as Renderer>::Error> + fn import_texture<R>(&mut self, renderer: &mut R) -> Result<R::TextureId, R::Error> where R: Renderer + ImportMem, - <R as Renderer>::TextureId: Send + Clone + 'static, + R::TextureId: Send + Clone + 'static, { - let texture_id = (TypeId::of::<<R as Renderer>::TextureId>(), renderer.id()); + let texture_id = (TypeId::of::<R::TextureId>(), renderer.id()); let current_commit = self.damage_bag.current_commit(); let last_commit = self.renderer_seen.get(&texture_id).copied(); let buffer_damage = self @@ -592,10 +485,10 @@ impl<R: Renderer> MemoryRenderBufferRenderElement<R> { src: Option<Rectangle<f64, Logical>>, size: Option<Size<i32, Logical>>, kind: Kind, - ) -> Result<Self, <R as Renderer>::Error> + ) -> Result<Self, R::Error> where R: ImportMem, - <R as Renderer>::TextureId: Send + Clone + 'static, + R::TextureId: Send + Clone + 'static, { let mut inner = buffer.inner.lock().unwrap(); let texture = inner.import_texture(renderer)?; @@ -737,18 +630,18 @@ impl<R: Renderer> Element for MemoryRenderBufferRenderElement<R> { impl<R> RenderElement<R> for MemoryRenderBufferRenderElement<R> where R: Renderer + ImportMem, - <R as Renderer>::TextureId: 'static, + R::TextureId: 'static, { #[instrument(level = "trace", skip(self, frame))] #[profiling::function] - fn draw<'a>( + fn draw( &self, - frame: &mut <R as Renderer>::Frame<'a>, + frame: &mut R::Frame<'_, '_>, src: Rectangle<f64, Buffer>, dst: Rectangle<i32, Physical>, damage: &[Rectangle<i32, Physical>], opaque_regions: &[Rectangle<i32, Physical>], - ) -> Result<(), <R as Renderer>::Error> { + ) -> Result<(), R::Error> { frame.render_texture_from_to( &self.texture, src, diff --git a/src/backend/renderer/element/mod.rs b/src/backend/renderer/element/mod.rs index 2a378b2002ee..bad491936ed1 100644 --- a/src/backend/renderer/element/mod.rs +++ b/src/backend/renderer/element/mod.rs @@ -385,7 +385,7 @@ pub trait RenderElement<R: Renderer>: Element { /// Draw this element fn draw( &self, - frame: &mut <R as Renderer>::Frame<'_>, + frame: &mut R::Frame<'_, '_>, src: Rectangle<f64, BufferCoords>, dst: Rectangle<i32, Physical>, damage: &[Rectangle<i32, Physical>], @@ -474,7 +474,7 @@ where fn draw( &self, - frame: &mut <R as Renderer>::Frame<'_>, + frame: &mut R::Frame<'_, '_>, src: Rectangle<f64, BufferCoords>, dst: Rectangle<i32, Physical>, damage: &[Rectangle<i32, Physical>], @@ -580,7 +580,7 @@ macro_rules! render_elements_internal { $vis enum $name<$lt, $renderer> where $renderer: $crate::backend::renderer::Renderer, - <$renderer as $crate::backend::renderer::Renderer>::TextureId: 'static, + <$renderer as $crate::backend::renderer::RendererSuper>::TextureId: 'static, { $( $( @@ -597,7 +597,7 @@ macro_rules! render_elements_internal { $vis enum $name<$lt, $renderer, $($custom),+> where $renderer: $crate::backend::renderer::Renderer, - <$renderer as $crate::backend::renderer::Renderer>::TextureId: 'static, + <$renderer as $crate::backend::renderer::RendererSuper>::TextureId: 'static, $( $custom: $crate::backend::renderer::element::RenderElement<$renderer>, )+ @@ -758,18 +758,18 @@ macro_rules! render_elements_internal { (@draw <$renderer:ty>; $($(#[$meta:meta])* $body:ident=$field:ty $(as <$other_renderer:ty>)?),* $(,)?) => { fn draw( &self, - frame: &mut <$renderer as $crate::backend::renderer::Renderer>::Frame<'_>, + frame: &mut <$renderer as $crate::backend::renderer::RendererSuper>::Frame<'_, '_>, src: $crate::utils::Rectangle<f64, $crate::utils::Buffer>, dst: $crate::utils::Rectangle<i32, $crate::utils::Physical>, damage: &[$crate::utils::Rectangle<i32, $crate::utils::Physical>], opaque_regions: &[$crate::utils::Rectangle<i32, $crate::utils::Physical>], - ) -> Result<(), <$renderer as $crate::backend::renderer::Renderer>::Error> + ) -> Result<(), <$renderer as $crate::backend::renderer::RendererSuper>::Error> where $( $( $renderer: std::convert::AsMut<$other_renderer>, - <$renderer as $crate::backend::renderer::Renderer>::Frame: std::convert::AsMut<<$other_renderer as $crate::backend::renderer::Renderer>::Frame>, - <$other_renderer as $crate::backend::renderer::Renderer>::Error: Into<<$renderer as $crate::backend::renderer::Renderer>::Error>, + <$renderer as $crate::backend::renderer::RendererSuper>::Frame: std::convert::AsMut<<$other_renderer as $crate::backend::renderer::RendererSuper>::Frame>, + <$other_renderer as $crate::backend::renderer::RendererSuper>::Error: Into<<$renderer as $crate::backend::renderer::RendererSuper>::Error>, )* )* { @@ -803,12 +803,12 @@ macro_rules! render_elements_internal { (@draw $renderer:ty; $($(#[$meta:meta])* $body:ident=$field:ty $(as <$other_renderer:ty>)?),* $(,)?) => { fn draw( &self, - frame: &mut <$renderer as $crate::backend::renderer::Renderer>::Frame<'_>, + frame: &mut <$renderer as $crate::backend::renderer::RendererSuper>::Frame<'_, '_>, src: $crate::utils::Rectangle<f64, $crate::utils::Buffer>, dst: $crate::utils::Rectangle<i32, $crate::utils::Physical>, damage: &[$crate::utils::Rectangle<i32, $crate::utils::Physical>], opaque_regions: &[$crate::utils::Rectangle<i32, $crate::utils::Physical>], - ) -> Result<(), <$renderer as $crate::backend::renderer::Renderer>::Error> + ) -> Result<(), <$renderer as $crate::backend::renderer::RendererSuper>::Error> { match self { $( @@ -842,7 +842,7 @@ macro_rules! render_elements_internal { impl<$renderer> $crate::backend::renderer::element::Element for $name<$renderer> where $renderer: $crate::backend::renderer::Renderer, - <$renderer as $crate::backend::renderer::Renderer>::TextureId: 'static, + <$renderer as $crate::backend::renderer::RendererSuper>::TextureId: 'static, $($($target: $bound $(+ $additional_bound)*),+)? { $crate::render_elements_internal!(@body $($tail)*); @@ -850,7 +850,7 @@ macro_rules! render_elements_internal { impl<$renderer> $crate::backend::renderer::element::RenderElement<$renderer> for $name<$renderer> where $renderer: $crate::backend::renderer::Renderer, - <$renderer as $crate::backend::renderer::Renderer>::TextureId: 'static, + <$renderer as $crate::backend::renderer::RendererSuper>::TextureId: 'static, $($($target: $bound $(+ $additional_bound)*),+)? { $crate::render_elements_internal!(@draw <$renderer>; $($tail)*); @@ -860,7 +860,7 @@ macro_rules! render_elements_internal { impl<$lt, $renderer> $crate::backend::renderer::element::Element for $name<$lt, $renderer> where $renderer: $crate::backend::renderer::Renderer, - <$renderer as $crate::backend::renderer::Renderer>::TextureId: 'static, + <$renderer as $crate::backend::renderer::RendererSuper>::TextureId: 'static, $($($target: $bound $(+ $additional_bound)*),+)? { $crate::render_elements_internal!(@body $($tail)*); @@ -868,7 +868,7 @@ macro_rules! render_elements_internal { impl<$lt, $renderer> $crate::backend::renderer::element::RenderElement<$renderer> for $name<$lt, $renderer> where $renderer: $crate::backend::renderer::Renderer, - <$renderer as $crate::backend::renderer::Renderer>::TextureId: 'static, + <$renderer as $crate::backend::renderer::RendererSuper>::TextureId: 'static, $($($target: $bound $(+ $additional_bound)*),+)? { $crate::render_elements_internal!(@draw <$renderer>; $($tail)*); @@ -878,7 +878,7 @@ macro_rules! render_elements_internal { impl<$renderer, $($custom),+> $crate::backend::renderer::element::Element for $name<$renderer, $($custom),+> where $renderer: $crate::backend::renderer::Renderer, - <$renderer as $crate::backend::renderer::Renderer>::TextureId: 'static, + <$renderer as $crate::backend::renderer::RendererSuper>::TextureId: 'static, $( $custom: $crate::backend::renderer::element::RenderElement<$renderer> + $crate::backend::renderer::element::Element, )+ @@ -889,7 +889,7 @@ macro_rules! render_elements_internal { impl<$renderer, $($custom),+> $crate::backend::renderer::element::RenderElement<$renderer> for $name<$renderer, $($custom),+> where $renderer: $crate::backend::renderer::Renderer, - <$renderer as $crate::backend::renderer::Renderer>::TextureId: 'static, + <$renderer as $crate::backend::renderer::RendererSuper>::TextureId: 'static, $( $custom: $crate::backend::renderer::element::RenderElement<$renderer> + $crate::backend::renderer::element::Element, )+ @@ -902,7 +902,7 @@ macro_rules! render_elements_internal { impl<$lt, $renderer, $($custom),+> $crate::backend::renderer::element::Element for $name<$lt, $renderer, $($custom),+> where $renderer: $crate::backend::renderer::Renderer, - <$renderer as $crate::backend::renderer::Renderer>::TextureId: 'static, + <$renderer as $crate::backend::renderer::RendererSuper>::TextureId: 'static, $( $custom: $crate::backend::renderer::element::RenderElement<$renderer> + $crate::backend::renderer::element::Element, )+ @@ -913,7 +913,7 @@ macro_rules! render_elements_internal { impl<$lt, $renderer, $($custom),+> $crate::backend::renderer::element::RenderElement<$renderer> for $name<$lt, $renderer, $($custom),+> where $renderer: $crate::backend::renderer::Renderer, - <$renderer as $crate::backend::renderer::Renderer>::TextureId: 'static, + <$renderer as $crate::backend::renderer::RendererSuper>::TextureId: 'static, $( $custom: $crate::backend::renderer::element::RenderElement<$renderer> + $crate::backend::renderer::element::Element, )+ @@ -930,7 +930,7 @@ macro_rules! render_elements_internal { impl<$renderer> $crate::backend::renderer::element::RenderElement<$renderer> for $name where $renderer: $crate::backend::renderer::Renderer, - <$renderer as $crate::backend::renderer::Renderer>::TextureId: 'static, + <$renderer as $crate::backend::renderer::RendererSuper>::TextureId: 'static, { $crate::render_elements_internal!(@draw <$renderer>; $($tail)*); } @@ -1146,12 +1146,12 @@ macro_rules! render_elements_internal { /// # impl<R: Renderer> RenderElement<R> for MyRenderElement1 { /// # fn draw( /// # &self, -/// # _frame: &mut <R as Renderer>::Frame<'_>, +/// # _frame: &mut R::Frame<'_, '_>, /// # _src: Rectangle<f64, Buffer>, /// # _dst: Rectangle<i32, Physical>, /// # _damage: &[Rectangle<i32, Physical>], /// # _opaque_regions: &[Rectangle<i32, Physical>], -/// # ) -> Result<(), <R as Renderer>::Error> { +/// # ) -> Result<(), R::Error> { /// # unimplemented!() /// # } /// # } @@ -1175,14 +1175,14 @@ macro_rules! render_elements_internal { /// # } /// # /// # impl<R: Renderer> RenderElement<R> for MyRenderElement2 { -/// # fn draw<'a>( +/// # fn draw( /// # &self, -/// # _frame: &mut <R as Renderer>::Frame<'a>, +/// # _frame: &mut R::Frame<'_, '_>, /// # _src: Rectangle<f64, Buffer>, /// # _dst: Rectangle<i32, Physical>, /// # _damage: &[Rectangle<i32, Physical>], /// # _opaque_regions: &[Rectangle<i32, Physical>], -/// # ) -> Result<(), <R as Renderer>::Error> { +/// # ) -> Result<(), R::Error> { /// # unimplemented!() /// # } /// # } @@ -1251,97 +1251,15 @@ macro_rules! render_elements_internal { /// # use smithay::{ /// # backend::{ /// # allocator::Fourcc, -/// # renderer::{Color32F, DebugFlags, Frame, Renderer, Texture, TextureFilter, sync::SyncPoint}, +/// # renderer::{Color32F, DebugFlags, Frame, Renderer, Texture, TextureFilter, sync::SyncPoint, gles::{GlesRenderer, GlesTexture}}, /// # }, /// # utils::{Buffer, Physical, Rectangle, Size, Transform}, /// # }; -/// # -/// # #[derive(Clone, Debug)] -/// # struct MyRendererTextureId; -/// # -/// # impl Texture for MyRendererTextureId { -/// # fn width(&self) -> u32 { -/// # unimplemented!() -/// # } -/// # fn height(&self) -> u32 { -/// # unimplemented!() -/// # } -/// # fn format(&self) -> Option<Fourcc> { -/// # unimplemented!() -/// # } -/// # } -/// # -/// # struct MyRendererFrame; -/// # -/// # impl Frame for MyRendererFrame { -/// # type Error = std::convert::Infallible; -/// # type TextureId = MyRendererTextureId; -/// # -/// # fn id(&self) -> usize { unimplemented!() } -/// # fn clear(&mut self, _: Color32F, _: &[Rectangle<i32, Physical>]) -> Result<(), Self::Error> { -/// # unimplemented!() -/// # } -/// # fn draw_solid( -/// # &mut self, -/// # _dst: Rectangle<i32, Physical>, -/// # _damage: &[Rectangle<i32, Physical>], -/// # _color: Color32F, -/// # ) -> Result<(), Self::Error> { -/// # unimplemented!() -/// # } -/// # fn render_texture_from_to( -/// # &mut self, -/// # _: &Self::TextureId, -/// # _: Rectangle<f64, Buffer>, -/// # _: Rectangle<i32, Physical>, -/// # _: &[Rectangle<i32, Physical>], -/// # _: &[Rectangle<i32, Physical>], -/// # _: Transform, -/// # _: f32, -/// # ) -> Result<(), Self::Error> { -/// # unimplemented!() -/// # } -/// # fn transformation(&self) -> Transform { -/// # unimplemented!() -/// # } -/// # fn finish(self) -> Result<SyncPoint, Self::Error> { unimplemented!() } -/// # fn wait(&mut self, sync: &SyncPoint) -> Result<(), Self::Error> { unimplemented!() } -/// # } -/// # -/// # #[derive(Debug)] -/// # struct MyRenderer; -/// # -/// # impl Renderer for MyRenderer { -/// # type Error = std::convert::Infallible; -/// # type TextureId = MyRendererTextureId; -/// # type Frame<'a> = MyRendererFrame; -/// # -/// # fn id(&self) -> usize { -/// # unimplemented!() -/// # } -/// # fn downscale_filter(&mut self, _: TextureFilter) -> Result<(), Self::Error> { -/// # unimplemented!() -/// # } -/// # fn upscale_filter(&mut self, _: TextureFilter) -> Result<(), Self::Error> { -/// # unimplemented!() -/// # } -/// # fn set_debug_flags(&mut self, flags: DebugFlags) { -/// # unimplemented!() -/// # } -/// # fn debug_flags(&self) -> DebugFlags { -/// # unimplemented!() -/// # } -/// # fn render(&mut self, _: Size<i32, Physical>, _: Transform) -> Result<Self::Frame<'_>, Self::Error> -/// # { -/// # unimplemented!() -/// # } -/// # fn wait(&mut self, sync: &SyncPoint) -> Result<(), Self::Error> { unimplemented!() } -/// # } /// use smithay::backend::renderer::element::{render_elements, texture::TextureRenderElement}; /// /// render_elements! { -/// MyRenderElements<=MyRenderer>; -/// Texture=TextureRenderElement<MyRendererTextureId>, +/// MyRenderElements<=GlesRenderer>; +/// Texture=TextureRenderElement<GlesTexture>, /// } /// ``` #[macro_export] @@ -1475,12 +1393,12 @@ where { fn draw( &self, - frame: &mut <R as Renderer>::Frame<'_>, + frame: &mut R::Frame<'_, '_>, src: Rectangle<f64, BufferCoords>, dst: Rectangle<i32, Physical>, damage: &[Rectangle<i32, Physical>], opaque_regions: &[Rectangle<i32, Physical>], - ) -> Result<(), <R as Renderer>::Error> { + ) -> Result<(), R::Error> { self.0.draw(frame, src, dst, damage, opaque_regions) } diff --git a/src/backend/renderer/element/solid.rs b/src/backend/renderer/element/solid.rs index 95b06b887e91..122507d223ef 100644 --- a/src/backend/renderer/element/solid.rs +++ b/src/backend/renderer/element/solid.rs @@ -6,115 +6,10 @@ //! # use smithay::{ //! # backend::{ //! # allocator::Fourcc, -//! # renderer::{Color32F, DebugFlags, Frame, ImportMem, Renderer, Texture, TextureFilter, sync::SyncPoint}, +//! # renderer::{Color32F, DebugFlags, Frame, ImportMem, Renderer, Texture, TextureFilter, sync::SyncPoint, test::{DummyRenderer, DummyFramebuffer}}, //! # }, //! # utils::{Buffer, Physical, Rectangle, Transform}, //! # }; -//! # #[derive(Clone, Debug)] -//! # struct FakeTexture; -//! # -//! # impl Texture for FakeTexture { -//! # fn width(&self) -> u32 { -//! # unimplemented!() -//! # } -//! # fn height(&self) -> u32 { -//! # unimplemented!() -//! # } -//! # fn format(&self) -> Option<Fourcc> { -//! # unimplemented!() -//! # } -//! # } -//! # -//! # struct FakeFrame; -//! # -//! # impl Frame for FakeFrame { -//! # type Error = std::convert::Infallible; -//! # type TextureId = FakeTexture; -//! # -//! # fn id(&self) -> usize { -//! # unimplemented!() -//! # } -//! # fn clear(&mut self, _: Color32F, _: &[Rectangle<i32, Physical>]) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn draw_solid( -//! # &mut self, -//! # _dst: Rectangle<i32, Physical>, -//! # _damage: &[Rectangle<i32, Physical>], -//! # _color: Color32F, -//! # ) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn render_texture_from_to( -//! # &mut self, -//! # _: &Self::TextureId, -//! # _: Rectangle<f64, Buffer>, -//! # _: Rectangle<i32, Physical>, -//! # _: &[Rectangle<i32, Physical>], -//! # _: &[Rectangle<i32, Physical>], -//! # _: Transform, -//! # _: f32, -//! # ) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn transformation(&self) -> Transform { -//! # unimplemented!() -//! # } -//! # fn finish(self) -> Result<SyncPoint, Self::Error> { -//! # unimplemented!() -//! # } -//! # fn wait(&mut self, sync: &SyncPoint) -> Result<(), Self::Error> { unimplemented!() } -//! # } -//! # -//! # #[derive(Debug)] -//! # struct FakeRenderer; -//! # -//! # impl Renderer for FakeRenderer { -//! # type Error = std::convert::Infallible; -//! # type TextureId = FakeTexture; -//! # type Frame<'a> = FakeFrame; -//! # -//! # fn id(&self) -> usize { -//! # unimplemented!() -//! # } -//! # fn downscale_filter(&mut self, _: TextureFilter) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn upscale_filter(&mut self, _: TextureFilter) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn set_debug_flags(&mut self, _: DebugFlags) { -//! # unimplemented!() -//! # } -//! # fn debug_flags(&self) -> DebugFlags { -//! # unimplemented!() -//! # } -//! # fn render(&mut self, _: Size<i32, Physical>, _: Transform) -> Result<Self::Frame<'_>, Self::Error> { -//! # unimplemented!() -//! # } -//! # fn wait(&mut self, sync: &SyncPoint) -> Result<(), Self::Error> { unimplemented!() } -//! # } -//! # -//! # impl ImportMem for FakeRenderer { -//! # fn import_memory( -//! # &mut self, -//! # _: &[u8], -//! # _: Fourcc, -//! # _: Size<i32, Buffer>, -//! # _: bool, -//! # ) -> Result<Self::TextureId, Self::Error> { -//! # unimplemented!() -//! # } -//! # fn update_memory( -//! # &mut self, -//! # _: &Self::TextureId, -//! # _: &[u8], -//! # _: Rectangle<i32, Buffer>, -//! # ) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn mem_formats(&self) -> Box<(dyn Iterator<Item=Fourcc> + 'static)> { unimplemented!() } -//! # } //! use smithay::{ //! backend::renderer::{ //! damage::OutputDamageTracker, @@ -135,7 +30,8 @@ //! //! // Initialize a static damage tracked renderer //! let mut damage_tracker = OutputDamageTracker::new((800, 600), 1.0, Transform::Normal); -//! # let mut renderer = FakeRenderer; +//! # let mut renderer = DummyRenderer; +//! # let mut framebuffer = DummyFramebuffer; //! //! loop { //! // Create a render element from the buffer @@ -144,7 +40,7 @@ //! //! // Render the element(s) //! damage_tracker -//! .render_output(&mut renderer, 0, &[&render_element], [0.8, 0.8, 0.9, 1.0]) +//! .render_output(&mut renderer, &mut framebuffer, 0, &[&render_element], [0.8, 0.8, 0.9, 1.0]) //! .expect("failed to render output"); //! } //! ``` @@ -325,12 +221,12 @@ impl<R: Renderer> RenderElement<R> for SolidColorRenderElement { #[profiling::function] fn draw( &self, - frame: &mut <R as Renderer>::Frame<'_>, + frame: &mut R::Frame<'_, '_>, _src: Rectangle<f64, Buffer>, dst: Rectangle<i32, Physical>, damage: &[Rectangle<i32, Physical>], _opaque_regions: &[Rectangle<i32, Physical>], - ) -> Result<(), <R as Renderer>::Error> { + ) -> Result<(), R::Error> { frame.draw_solid(dst, damage, self.color) } diff --git a/src/backend/renderer/element/surface.rs b/src/backend/renderer/element/surface.rs index 8955e463d9f7..cca38f40be8b 100644 --- a/src/backend/renderer/element/surface.rs +++ b/src/backend/renderer/element/surface.rs @@ -24,169 +24,11 @@ //! # backend::allocator::{Fourcc, dmabuf::Dmabuf}, //! # backend::renderer::{ //! # Color32F, DebugFlags, Frame, ImportDma, ImportDmaWl, ImportMem, ImportMemWl, Renderer, Texture, -//! # TextureFilter, sync::SyncPoint, +//! # TextureFilter, sync::SyncPoint, test::{DummyRenderer, DummyFramebuffer}, //! # }, //! # utils::{Buffer, Physical}, //! # wayland::compositor::SurfaceData, //! # }; -//! # -//! # #[derive(Clone, Debug)] -//! # struct FakeTexture; -//! # -//! # impl Texture for FakeTexture { -//! # fn width(&self) -> u32 { -//! # unimplemented!() -//! # } -//! # fn height(&self) -> u32 { -//! # unimplemented!() -//! # } -//! # fn format(&self) -> Option<Fourcc> { -//! # unimplemented!() -//! # } -//! # } -//! # -//! # struct FakeFrame; -//! # -//! # impl Frame for FakeFrame { -//! # type Error = std::convert::Infallible; -//! # type TextureId = FakeTexture; -//! # -//! # fn id(&self) -> usize { unimplemented!() } -//! # fn clear(&mut self, _: Color32F, _: &[Rectangle<i32, Physical>]) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn draw_solid( -//! # &mut self, -//! # _dst: Rectangle<i32, Physical>, -//! # _damage: &[Rectangle<i32, Physical>], -//! # _color: Color32F, -//! # ) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn render_texture_from_to( -//! # &mut self, -//! # _: &Self::TextureId, -//! # _: Rectangle<f64, Buffer>, -//! # _: Rectangle<i32, Physical>, -//! # _: &[Rectangle<i32, Physical>], -//! # _: &[Rectangle<i32, Physical>], -//! # _: Transform, -//! # _: f32, -//! # ) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn transformation(&self) -> Transform { -//! # unimplemented!() -//! # } -//! # fn finish(self) -> Result<SyncPoint, Self::Error> { unimplemented!() } -//! # fn wait(&mut self, sync: &SyncPoint) -> Result<(), Self::Error> { unimplemented!() } -//! # } -//! # -//! # #[derive(Debug)] -//! # struct FakeRenderer; -//! # -//! # impl Renderer for FakeRenderer { -//! # type Error = std::convert::Infallible; -//! # type TextureId = FakeTexture; -//! # type Frame<'a> = FakeFrame; -//! # -//! # fn id(&self) -> usize { -//! # unimplemented!() -//! # } -//! # fn downscale_filter(&mut self, _: TextureFilter) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn upscale_filter(&mut self, _: TextureFilter) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn set_debug_flags(&mut self, _: DebugFlags) { -//! # unimplemented!() -//! # } -//! # fn debug_flags(&self) -> DebugFlags { -//! # unimplemented!() -//! # } -//! # fn render(&mut self, _: Size<i32, Physical>, _: Transform) -> Result<Self::Frame<'_>, Self::Error> -//! # { -//! # unimplemented!() -//! # } -//! # fn wait(&mut self, sync: &SyncPoint) -> Result<(), Self::Error> { unimplemented!() } -//! # } -//! # -//! # impl ImportMem for FakeRenderer { -//! # fn import_memory( -//! # &mut self, -//! # _: &[u8], -//! # _: Fourcc, -//! # _: Size<i32, Buffer>, -//! # _: bool, -//! # ) -> Result<Self::TextureId, Self::Error> { -//! # unimplemented!() -//! # } -//! # fn update_memory( -//! # &mut self, -//! # _: &Self::TextureId, -//! # _: &[u8], -//! # _: Rectangle<i32, Buffer>, -//! # ) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn mem_formats(&self) -> Box<dyn Iterator<Item=Fourcc>> { -//! # unimplemented!() -//! # } -//! # } -//! # -//! # impl ImportMemWl for FakeRenderer { -//! # fn import_shm_buffer( -//! # &mut self, -//! # _buffer: &wayland_server::protocol::wl_buffer::WlBuffer, -//! # _surface: Option<&SurfaceData>, -//! # _damage: &[Rectangle<i32, Buffer>], -//! # ) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error> { -//! # unimplemented!() -//! # } -//! # } -//! # #[cfg(all( -//! # feature = "wayland_frontend", -//! # feature = "backend_egl", -//! # feature = "use_system_lib" -//! # ))] -//! # impl ImportEgl for FakeRenderer { -//! # fn bind_wl_display( -//! # &mut self, -//! # _display: &wayland_server::DisplayHandle, -//! # ) -> Result<(), egl::Error> { -//! # unimplemented!() -//! # } -//! # -//! # fn unbind_wl_display(&mut self) { -//! # unimplemented!() -//! # } -//! # -//! # fn egl_reader(&self) -> Option<&EGLBufferReader> { -//! # unimplemented!() -//! # } -//! # -//! # fn import_egl_buffer( -//! # &mut self, -//! # _buffer: &wayland_server::protocol::wl_buffer::WlBuffer, -//! # _surface: Option<&SurfaceData>, -//! # _damage: &[Rectangle<i32, Buffer>], -//! # ) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error> { -//! # unimplemented!() -//! # } -//! # } -//! # -//! # impl ImportDma for FakeRenderer { -//! # fn import_dmabuf( -//! # &mut self, -//! # _dmabuf: &Dmabuf, -//! # _damage: Option<&[Rectangle<i32, Buffer>]>, -//! # ) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error> { -//! # unimplemented!() -//! # } -//! # } -//! # -//! # impl ImportDmaWl for FakeRenderer {} //! use smithay::{ //! backend::renderer::{ //! damage::OutputDamageTracker, @@ -204,17 +46,18 @@ //! //! // Initialize a static damage tracked renderer //! let mut damage_tracker = OutputDamageTracker::new((800, 600), 1.0, Transform::Normal); -//! # let mut renderer = FakeRenderer; +//! # let mut renderer = DummyRenderer; +//! # let mut framebuffer = DummyFramebuffer; //! //! loop { //! // Create the render elements from the surface //! let location = Point::from((100, 100)); -//! let render_elements: Vec<WaylandSurfaceRenderElement<FakeRenderer>> = +//! let render_elements: Vec<WaylandSurfaceRenderElement<DummyRenderer>> = //! render_elements_from_surface_tree(&mut renderer, &surface, location, 1.0, 1.0, Kind::Unspecified); //! //! // Render the element(s) //! damage_tracker -//! .render_output(&mut renderer, 0, &*render_elements, [0.8, 0.8, 0.9, 1.0]) +//! .render_output(&mut renderer, &mut framebuffer, 0, &*render_elements, [0.8, 0.8, 0.9, 1.0]) //! .expect("failed to render output"); //! } //! ``` @@ -254,7 +97,7 @@ pub fn render_elements_from_surface_tree<R, E>( ) -> Vec<E> where R: Renderer + ImportAll, - <R as Renderer>::TextureId: Clone + 'static, + R::TextureId: Clone + 'static, E: From<WaylandSurfaceRenderElement<R>>, { let location = location.into().to_f64(); @@ -314,7 +157,7 @@ where #[derive(Debug)] pub enum WaylandSurfaceTexture<R: Renderer> { /// A renderer texture - Texture(<R as Renderer>::TextureId), + Texture(R::TextureId), /// A solid color SolidColor(Color32F), } @@ -355,9 +198,9 @@ impl<R: Renderer + ImportAll> WaylandSurfaceRenderElement<R> { location: Point<f64, Physical>, alpha: f32, kind: Kind, - ) -> Result<Option<Self>, <R as Renderer>::Error> + ) -> Result<Option<Self>, R::Error> where - <R as Renderer>::TextureId: Clone + 'static, + R::TextureId: Clone + 'static, { let id = Id::from_wayland_resource(surface); crate::backend::renderer::utils::import_surface(renderer, states)?; @@ -387,7 +230,7 @@ impl<R: Renderer + ImportAll> WaylandSurfaceRenderElement<R> { data: &RendererSurfaceState, ) -> Option<Self> where - <R as Renderer>::TextureId: Clone + 'static, + R::TextureId: Clone + 'static, { let buffer = data.buffer()?.clone(); @@ -528,7 +371,7 @@ impl<R: Renderer + ImportAll> Element for WaylandSurfaceRenderElement<R> { impl<R> RenderElement<R> for WaylandSurfaceRenderElement<R> where R: Renderer + ImportAll, - <R as Renderer>::TextureId: Texture + 'static, + R::TextureId: Texture + 'static, { #[inline] fn underlying_storage(&self, _renderer: &mut R) -> Option<UnderlyingStorage<'_>> { @@ -537,9 +380,9 @@ where #[instrument(level = "trace", skip(frame))] #[profiling::function] - fn draw<'a>( + fn draw( &self, - frame: &mut <R as Renderer>::Frame<'a>, + frame: &mut R::Frame<'_, '_>, src: Rectangle<f64, BufferCoords>, dst: Rectangle<i32, Physical>, damage: &[Rectangle<i32, Physical>], diff --git a/src/backend/renderer/element/tests.rs b/src/backend/renderer/element/tests.rs index 609df784ec14..ccbbf6e965eb 100644 --- a/src/backend/renderer/element/tests.rs +++ b/src/backend/renderer/element/tests.rs @@ -35,23 +35,23 @@ render_elements! { } render_elements! { - TextureIdTest<R> where R: ImportMem, <R as Renderer>::TextureId: Clone; + TextureIdTest<R> where R: ImportMem, R::TextureId: Clone; Memory=ImportMemRenderElement, } render_elements! { - TextureIdTest1<R> where R: ImportMem, <R as Renderer>::TextureId: 'static; + TextureIdTest1<R> where R: ImportMem, R::TextureId: 'static; Memory=ImportMemRenderElement, } render_elements! { - TextureIdTest2<'a, R, C> where R: ImportMem, <R as Renderer>::TextureId: 'a; + TextureIdTest2<'a, R, C> where R: ImportMem, R::TextureId: 'a; Memory=ImportMemRenderElement, Custom=&'a C, } render_elements! { - TextureIdTest3<'a, R, C> where R: ImportMem, <R as Renderer>::TextureId: Clone + 'a; + TextureIdTest3<'a, R, C> where R: ImportMem, R::TextureId: Clone + 'a; Memory=ImportMemRenderElement, Custom=&'a C, } @@ -145,12 +145,12 @@ where { fn draw( &self, - _frame: &mut <R as Renderer>::Frame<'_>, + _frame: &mut R::Frame<'_, '_>, _src: Rectangle<f64, Buffer>, _dst: Rectangle<i32, Physical>, _damage: &[Rectangle<i32, Physical>], _opaque_regions: &[Rectangle<i32, Physical>], - ) -> Result<(), <R as Renderer>::Error> { + ) -> Result<(), R::Error> { todo!() } } @@ -183,12 +183,12 @@ where { fn draw( &self, - _frame: &mut <R as Renderer>::Frame<'_>, + _frame: &mut R::Frame<'_, '_>, _src: Rectangle<f64, Buffer>, _dst: Rectangle<i32, Physical>, _damage: &[Rectangle<i32, Physical>], _opaque_regions: &[Rectangle<i32, Physical>], - ) -> Result<(), <R as Renderer>::Error> { + ) -> Result<(), R::Error> { todo!() } } @@ -230,12 +230,12 @@ where { fn draw( &self, - _frame: &mut <R as Renderer>::Frame<'_>, + _frame: &mut R::Frame<'_, '_>, _src: Rectangle<f64, Buffer>, _dst: Rectangle<i32, Physical>, _damage: &[Rectangle<i32, Physical>], _opaque_regions: &[Rectangle<i32, Physical>], - ) -> Result<(), <R as Renderer>::Error> { + ) -> Result<(), R::Error> { todo!() } } @@ -276,12 +276,12 @@ where { fn draw( &self, - _frame: &mut <R as Renderer>::Frame<'_>, + _frame: &mut R::Frame<'_, '_>, _src: Rectangle<f64, Buffer>, _dst: Rectangle<i32, Physical>, _damage: &[Rectangle<i32, Physical>], _opaque_regions: &[Rectangle<i32, Physical>], - ) -> Result<(), <R as Renderer>::Error> { + ) -> Result<(), R::Error> { todo!() } } diff --git a/src/backend/renderer/element/texture.rs b/src/backend/renderer/element/texture.rs index d10c4c611a2b..a9f69262d3b3 100644 --- a/src/backend/renderer/element/texture.rs +++ b/src/backend/renderer/element/texture.rs @@ -41,114 +41,9 @@ //! //! ```no_run //! # use smithay::{ -//! # backend::renderer::{Color32F, DebugFlags, Frame, ImportMem, Renderer, Texture, TextureFilter, sync::SyncPoint}, +//! # backend::renderer::{Color32F, DebugFlags, Frame, ImportMem, Renderer, Texture, TextureFilter, sync::SyncPoint, test::{DummyRenderer, DummyFramebuffer}}, //! # utils::{Buffer, Physical, Rectangle, Size}, //! # }; -//! # -//! # #[derive(Clone, Debug)] -//! # struct FakeTexture; -//! # -//! # impl Texture for FakeTexture { -//! # fn width(&self) -> u32 { -//! # unimplemented!() -//! # } -//! # fn height(&self) -> u32 { -//! # unimplemented!() -//! # } -//! # fn format(&self) -> Option<Fourcc> { -//! # unimplemented!() -//! # } -//! # } -//! # -//! # struct FakeFrame; -//! # -//! # impl Frame for FakeFrame { -//! # type Error = std::convert::Infallible; -//! # type TextureId = FakeTexture; -//! # -//! # fn id(&self) -> usize { unimplemented!() } -//! # fn clear(&mut self, _: Color32F, _: &[Rectangle<i32, Physical>]) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn draw_solid( -//! # &mut self, -//! # _dst: Rectangle<i32, Physical>, -//! # _damage: &[Rectangle<i32, Physical>], -//! # _color: Color32F, -//! # ) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn render_texture_from_to( -//! # &mut self, -//! # _: &Self::TextureId, -//! # _: Rectangle<f64, Buffer>, -//! # _: Rectangle<i32, Physical>, -//! # _: &[Rectangle<i32, Physical>], -//! # _: &[Rectangle<i32, Physical>], -//! # _: Transform, -//! # _: f32, -//! # ) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn transformation(&self) -> Transform { -//! # unimplemented!() -//! # } -//! # fn finish(self) -> Result<SyncPoint, Self::Error> { unimplemented!() } -//! # fn wait(&mut self, sync: &SyncPoint) -> Result<(), Self::Error> { unimplemented!() } -//! # } -//! # -//! # #[derive(Debug)] -//! # struct FakeRenderer; -//! # -//! # impl Renderer for FakeRenderer { -//! # type Error = std::convert::Infallible; -//! # type TextureId = FakeTexture; -//! # type Frame<'a> = FakeFrame; -//! # -//! # fn id(&self) -> usize { -//! # unimplemented!() -//! # } -//! # fn downscale_filter(&mut self, _: TextureFilter) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn upscale_filter(&mut self, _: TextureFilter) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn set_debug_flags(&mut self, _: DebugFlags) { -//! # unimplemented!() -//! # } -//! # fn debug_flags(&self) -> DebugFlags { -//! # unimplemented!() -//! # } -//! # fn render(&mut self, _: Size<i32, Physical>, _: Transform) -> Result<Self::Frame<'_>, Self::Error> -//! # { -//! # unimplemented!() -//! # } -//! # fn wait(&mut self, sync: &SyncPoint) -> Result<(), Self::Error> { unimplemented!() } -//! # } -//! # -//! # impl ImportMem for FakeRenderer { -//! # fn import_memory( -//! # &mut self, -//! # _: &[u8], -//! # _: Fourcc, -//! # _: Size<i32, Buffer>, -//! # _: bool, -//! # ) -> Result<Self::TextureId, Self::Error> { -//! # unimplemented!() -//! # } -//! # fn update_memory( -//! # &mut self, -//! # _: &Self::TextureId, -//! # _: &[u8], -//! # _: Rectangle<i32, Buffer>, -//! # ) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn mem_formats(&self) -> Box<dyn Iterator<Item=Fourcc>> { -//! # unimplemented!() -//! # } -//! # } //! use smithay::{ //! backend::{ //! allocator::Fourcc, @@ -167,7 +62,8 @@ //! const HEIGHT: i32 = 10; //! //! let memory = vec![0; (WIDTH * 4 * HEIGHT) as usize]; -//! # let mut renderer = FakeRenderer; +//! # let mut renderer = DummyRenderer; +//! # let mut framebuffer = DummyFramebuffer; //! //! // Create the texture buffer from a chunk of memory //! let texture_buffer = TextureBuffer::from_memory( @@ -192,7 +88,7 @@ //! //! // Render the element(s) //! damage_tracker -//! .render_output(&mut renderer, 0, &[&render_element], [0.8, 0.8, 0.9, 1.0]) +//! .render_output(&mut renderer, &mut framebuffer, 0, &[&render_element], [0.8, 0.8, 0.9, 1.0]) //! .expect("failed to render output"); //! } //! ``` @@ -201,114 +97,9 @@ //! //! ```no_run //! # use smithay::{ -//! # backend::renderer::{Color32F, DebugFlags, Frame, ImportMem, Renderer, Texture, TextureFilter, sync::SyncPoint}, +//! # backend::renderer::{Color32F, DebugFlags, Frame, ImportMem, Renderer, Texture, TextureFilter, sync::SyncPoint, test::{DummyRenderer, DummyFramebuffer}}, //! # utils::{Buffer, Physical}, //! # }; -//! # -//! # #[derive(Clone, Debug)] -//! # struct FakeTexture; -//! # -//! # impl Texture for FakeTexture { -//! # fn width(&self) -> u32 { -//! # unimplemented!() -//! # } -//! # fn height(&self) -> u32 { -//! # unimplemented!() -//! # } -//! # fn format(&self) -> Option<Fourcc> { -//! # unimplemented!() -//! # } -//! # } -//! # -//! # struct FakeFrame; -//! # -//! # impl Frame for FakeFrame { -//! # type Error = std::convert::Infallible; -//! # type TextureId = FakeTexture; -//! # -//! # fn id(&self) -> usize { unimplemented!() } -//! # fn clear(&mut self, _: Color32F, _: &[Rectangle<i32, Physical>]) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn draw_solid( -//! # &mut self, -//! # _dst: Rectangle<i32, Physical>, -//! # _damage: &[Rectangle<i32, Physical>], -//! # _color: Color32F, -//! # ) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn render_texture_from_to( -//! # &mut self, -//! # _: &Self::TextureId, -//! # _: Rectangle<f64, Buffer>, -//! # _: Rectangle<i32, Physical>, -//! # _: &[Rectangle<i32, Physical>], -//! # _: &[Rectangle<i32, Physical>], -//! # _: Transform, -//! # _: f32, -//! # ) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn transformation(&self) -> Transform { -//! # unimplemented!() -//! # } -//! # fn finish(self) -> Result<SyncPoint, Self::Error> { unimplemented!() } -//! # fn wait(&mut self, sync: &SyncPoint) -> Result<(), Self::Error> { unimplemented!() } -//! # } -//! # -//! # #[derive(Debug)] -//! # struct FakeRenderer; -//! # -//! # impl Renderer for FakeRenderer { -//! # type Error = std::convert::Infallible; -//! # type TextureId = FakeTexture; -//! # type Frame<'a> = FakeFrame; -//! # -//! # fn id(&self) -> usize { -//! # unimplemented!() -//! # } -//! # fn downscale_filter(&mut self, _: TextureFilter) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn upscale_filter(&mut self, _: TextureFilter) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn set_debug_flags(&mut self, _: DebugFlags) { -//! # unimplemented!() -//! # } -//! # fn debug_flags(&self) -> DebugFlags { -//! # unimplemented!() -//! # } -//! # fn render(&mut self, _: Size<i32, Physical>, _: Transform) -> Result<Self::Frame<'_>, Self::Error> -//! # { -//! # unimplemented!() -//! # } -//! # fn wait(&mut self, sync: &SyncPoint) -> Result<(), Self::Error> { unimplemented!() } -//! # } -//! # -//! # impl ImportMem for FakeRenderer { -//! # fn import_memory( -//! # &mut self, -//! # _: &[u8], -//! # _: Fourcc, -//! # _: Size<i32, Buffer>, -//! # _: bool, -//! # ) -> Result<Self::TextureId, Self::Error> { -//! # unimplemented!() -//! # } -//! # fn update_memory( -//! # &mut self, -//! # _: &Self::TextureId, -//! # _: &[u8], -//! # _: Rectangle<i32, Buffer>, -//! # ) -> Result<(), Self::Error> { -//! # unimplemented!() -//! # } -//! # fn mem_formats(&self) -> Box<dyn Iterator<Item=Fourcc>> { -//! # unimplemented!() -//! # } -//! # } //! use std::time::{Duration, Instant}; //! //! use smithay::{ @@ -329,7 +120,8 @@ //! const HEIGHT: i32 = 10; //! //! let memory = vec![0; (WIDTH * 4 * HEIGHT) as usize]; -//! # let mut renderer = FakeRenderer; +//! # let mut renderer = DummyRenderer; +//! # let mut framebuffer = DummyFramebuffer; //! //! // Create the texture buffer from a chunk of memory //! let mut texture_render_buffer = TextureRenderBuffer::from_memory( @@ -397,7 +189,7 @@ //! //! // Render the element(s) //! damage_tracker -//! .render_output(&mut renderer, 0, &[&render_element], [0.8, 0.8, 0.9, 1.0]) +//! .render_output(&mut renderer, &mut framebuffer, 0, &[&render_element], [0.8, 0.8, 0.9, 1.0]) //! .expect("failed to render output"); //! } //! ``` @@ -460,7 +252,7 @@ impl<T> TextureBuffer<T> { scale: i32, transform: Transform, opaque_regions: Option<Vec<Rectangle<i32, Buffer>>>, - ) -> Result<Self, <R as Renderer>::Error> { + ) -> Result<Self, R::Error> { let texture = renderer.import_memory(data, format, size.into(), flipped)?; Ok(TextureBuffer::from_texture( renderer, @@ -523,7 +315,7 @@ impl<T: Texture> TextureRenderBuffer<T> { scale: i32, transform: Transform, opaque_regions: Option<Vec<Rectangle<i32, Buffer>>>, - ) -> Result<Self, <R as Renderer>::Error> { + ) -> Result<Self, R::Error> { let texture = renderer.import_memory(data, format, size.into(), flipped)?; Ok(TextureRenderBuffer::from_texture( renderer, @@ -558,7 +350,7 @@ impl<T: Texture> TextureRenderBuffer<T> { data: &[u8], region: Rectangle<i32, Buffer>, opaque_regions: Option<Vec<Rectangle<i32, Buffer>>>, - ) -> Result<(), <R as Renderer>::Error> { + ) -> Result<(), R::Error> { assert_eq!(self.renderer_id, renderer.id()); renderer.update_memory(&self.texture, data, region)?; self.damage_tracker.lock().unwrap().add([region]); @@ -894,14 +686,14 @@ where { #[instrument(level = "trace", skip(self, frame))] #[profiling::function] - fn draw<'a>( + fn draw( &self, - frame: &mut <R as Renderer>::Frame<'a>, + frame: &mut R::Frame<'_, '_>, src: Rectangle<f64, Buffer>, dst: Rectangle<i32, Physical>, damage: &[Rectangle<i32, Physical>], opaque_regions: &[Rectangle<i32, Physical>], - ) -> Result<(), <R as Renderer>::Error> { + ) -> Result<(), R::Error> { if frame.id() != self.renderer_id { warn!("trying to render texture from different renderer"); return Ok(()); diff --git a/src/backend/renderer/element/utils/elements.rs b/src/backend/renderer/element/utils/elements.rs index 563945283486..607909a0aacf 100644 --- a/src/backend/renderer/element/utils/elements.rs +++ b/src/backend/renderer/element/utils/elements.rs @@ -95,12 +95,12 @@ impl<E: Element> Element for RescaleRenderElement<E> { impl<R: Renderer, E: RenderElement<R>> RenderElement<R> for RescaleRenderElement<E> { fn draw( &self, - frame: &mut <R as Renderer>::Frame<'_>, + frame: &mut R::Frame<'_, '_>, src: crate::utils::Rectangle<f64, crate::utils::Buffer>, dst: crate::utils::Rectangle<i32, crate::utils::Physical>, damage: &[crate::utils::Rectangle<i32, crate::utils::Physical>], opaque_regions: &[crate::utils::Rectangle<i32, crate::utils::Physical>], - ) -> Result<(), <R as Renderer>::Error> { + ) -> Result<(), R::Error> { self.element.draw(frame, src, dst, damage, opaque_regions) } @@ -279,12 +279,12 @@ impl<E: Element> Element for CropRenderElement<E> { impl<R: Renderer, E: RenderElement<R>> RenderElement<R> for CropRenderElement<E> { fn draw( &self, - frame: &mut <R as Renderer>::Frame<'_>, + frame: &mut R::Frame<'_, '_>, src: crate::utils::Rectangle<f64, crate::utils::Buffer>, dst: crate::utils::Rectangle<i32, crate::utils::Physical>, damage: &[crate::utils::Rectangle<i32, crate::utils::Physical>], opaque_regions: &[crate::utils::Rectangle<i32, crate::utils::Physical>], - ) -> Result<(), <R as Renderer>::Error> { + ) -> Result<(), R::Error> { self.element.draw(frame, src, dst, damage, opaque_regions) } @@ -381,12 +381,12 @@ impl<E: Element> Element for RelocateRenderElement<E> { impl<R: Renderer, E: RenderElement<R>> RenderElement<R> for RelocateRenderElement<E> { fn draw( &self, - frame: &mut <R as Renderer>::Frame<'_>, + frame: &mut R::Frame<'_, '_>, src: crate::utils::Rectangle<f64, crate::utils::Buffer>, dst: crate::utils::Rectangle<i32, crate::utils::Physical>, damage: &[crate::utils::Rectangle<i32, crate::utils::Physical>], opaque_regions: &[crate::utils::Rectangle<i32, crate::utils::Physical>], - ) -> Result<(), <R as Renderer>::Error> { + ) -> Result<(), R::Error> { self.element.draw(frame, src, dst, damage, opaque_regions) } diff --git a/src/backend/renderer/gles/element.rs b/src/backend/renderer/gles/element.rs index 6d16fea50c02..ac3d3c7746b9 100644 --- a/src/backend/renderer/gles/element.rs +++ b/src/backend/renderer/gles/element.rs @@ -109,7 +109,7 @@ impl RenderElement<GlesRenderer> for PixelShaderElement { #[profiling::function] fn draw( &self, - frame: &mut GlesFrame<'_>, + frame: &mut GlesFrame<'_, '_>, _src: Rectangle<f64, Buffer>, dst: Rectangle<i32, Physical>, damage: &[Rectangle<i32, Physical>], @@ -204,7 +204,7 @@ impl RenderElement<GlesRenderer> for TextureShaderElement { #[profiling::function] fn draw( &self, - frame: &mut GlesFrame<'_>, + frame: &mut GlesFrame<'_, '_>, src: Rectangle<f64, Buffer>, dst: Rectangle<i32, Physical>, damage: &[Rectangle<i32, Physical>], diff --git a/src/backend/renderer/gles/mod.rs b/src/backend/renderer/gles/mod.rs index 4821de577b2f..736f761e3459 100644 --- a/src/backend/renderer/gles/mod.rs +++ b/src/backend/renderer/gles/mod.rs @@ -12,7 +12,7 @@ use std::{ sync::{ atomic::{AtomicBool, AtomicPtr, Ordering}, mpsc::{channel, Receiver, Sender}, - Arc, Mutex, RwLock, + Arc, Mutex, RwLock, RwLockWriteGuard, }, }; use tracing::{debug, error, info, info_span, instrument, span, span::EnteredSpan, trace, warn, Level}; @@ -35,7 +35,7 @@ use self::version::GlVersion; use super::{ sync::SyncPoint, Bind, Blit, Color32F, DebugFlags, ExportMem, Frame, ImportDma, ImportMem, Offscreen, - Renderer, Texture, TextureFilter, TextureMapping, Unbind, + Renderer, RendererSuper, Texture, TextureFilter, TextureMapping, }; use crate::backend::egl::{ ffi::egl::{self as ffi_egl, types::EGLImage}, @@ -135,39 +135,44 @@ impl Drop for GlesRenderbufferInternal { } } +/// A GL framebuffer #[derive(Debug)] -enum GlesTarget { +pub struct GlesTarget<'a>(GlesTargetInternal<'a>); + +#[derive(Debug)] +enum GlesTargetInternal<'a> { Image { // TODO: Ideally we would be able to share the texture between renderers with shared EGLContexts though. // But we definitly don't want to add user data to a dmabuf to facilitate this. Maybe use the EGLContexts userdata for storing the buffers? buf: GlesBuffer, - dmabuf: Dmabuf, + dmabuf: &'a mut Dmabuf, }, Surface { - surface: Rc<EGLSurface>, + surface: &'a mut EGLSurface, }, Texture { texture: GlesTexture, + sync_lock: RwLockWriteGuard<'a, TextureSync>, fbo: ffi::types::GLuint, destruction_callback_sender: Sender<CleanupResource>, }, Renderbuffer { - buf: GlesRenderbuffer, + buf: &'a mut GlesRenderbuffer, fbo: ffi::types::GLuint, }, } -impl GlesTarget { +impl GlesTargetInternal<'_> { fn format(&self) -> Option<(ffi::types::GLenum, bool)> { match self { - GlesTarget::Image { dmabuf, .. } => { - let format = crate::backend::allocator::Buffer::format(dmabuf).code; + GlesTargetInternal::Image { dmabuf, .. } => { + let format = crate::backend::allocator::Buffer::format(*dmabuf).code; let has_alpha = has_alpha(format); let (format, _, _) = fourcc_to_gl_formats(format)?; Some((format, has_alpha)) } - GlesTarget::Surface { surface, .. } => { + GlesTargetInternal::Surface { surface, .. } => { let format = surface.pixel_format(); let format = match (format.color_bits, format.alpha_bits) { (24, 8) => ffi::RGB8, @@ -178,23 +183,27 @@ impl GlesTarget { Some((format, true)) } - GlesTarget::Texture { texture, .. } => Some((texture.0.format?, texture.0.has_alpha)), - GlesTarget::Renderbuffer { buf, .. } => Some((buf.0.format, buf.0.has_alpha)), + GlesTargetInternal::Texture { texture, .. } => Some((texture.0.format?, texture.0.has_alpha)), + GlesTargetInternal::Renderbuffer { buf, .. } => Some((buf.0.format, buf.0.has_alpha)), } } #[profiling::function] fn make_current(&self, gl: &ffi::Gles2, egl: &EGLContext) -> Result<(), MakeCurrentError> { unsafe { - if let GlesTarget::Surface { surface, .. } = self { + if let GlesTargetInternal::Surface { surface, .. } = self { egl.make_current_with_surface(surface)?; gl.BindFramebuffer(ffi::FRAMEBUFFER, 0); } else { egl.make_current()?; match self { - GlesTarget::Image { ref buf, .. } => gl.BindFramebuffer(ffi::FRAMEBUFFER, buf.fbo), - GlesTarget::Texture { ref fbo, .. } => gl.BindFramebuffer(ffi::FRAMEBUFFER, *fbo), - GlesTarget::Renderbuffer { ref fbo, .. } => gl.BindFramebuffer(ffi::FRAMEBUFFER, *fbo), + GlesTargetInternal::Image { ref buf, .. } => { + gl.BindFramebuffer(ffi::FRAMEBUFFER, buf.fbo) + } + GlesTargetInternal::Texture { ref fbo, .. } => gl.BindFramebuffer(ffi::FRAMEBUFFER, *fbo), + GlesTargetInternal::Renderbuffer { ref fbo, .. } => { + gl.BindFramebuffer(ffi::FRAMEBUFFER, *fbo) + } _ => unreachable!(), } } @@ -203,17 +212,17 @@ impl GlesTarget { } } -impl Drop for GlesTarget { +impl Drop for GlesTargetInternal<'_> { fn drop(&mut self) { match self { - GlesTarget::Texture { + GlesTargetInternal::Texture { fbo, destruction_callback_sender, .. } => { let _ = destruction_callback_sender.send(CleanupResource::FramebufferObject(*fbo)); } - GlesTarget::Renderbuffer { buf, fbo, .. } => { + GlesTargetInternal::Renderbuffer { buf, fbo, .. } => { let _ = buf .0 .destruction_callback_sender @@ -246,7 +255,6 @@ pub enum Capability { /// A renderer utilizing OpenGL ES pub struct GlesRenderer { // state - target: Option<GlesTarget>, min_filter: TextureFilter, max_filter: TextureFilter, debug_flags: DebugFlags, @@ -288,12 +296,14 @@ pub struct GlesRenderer { /// Handle to the currently rendered frame during [`GlesRenderer::render`](Renderer::render). /// -/// Leaking this frame will prevent it from synchronizing the rendered framebuffer, -/// which might cause glitches. Additionally parts of the GL state might not be reset correctly, -/// causing unexpected results for later render commands. -/// The internal GL context and framebuffer will remain valid, no re-creation will be necessary. -pub struct GlesFrame<'frame> { +/// Leaking this frame will cause a variety of problems: +/// - It might prevent the frame from synchronizing the rendered framebuffer causing glitches. +/// - Depending on the bound target this can deadlock, if the same target is used later in any way. +/// - Additionally parts of the GL state might not be reset correctly, causing unexpected results for later render commands. +/// - The internal GL context and framebuffer will remain valid, no re-creation will be necessary. +pub struct GlesFrame<'frame, 'buffer> { renderer: &'frame mut GlesRenderer, + target: &'frame mut GlesTarget<'buffer>, current_projection: Matrix3<f32>, transform: Transform, size: Size<i32, Physical>, @@ -303,10 +313,11 @@ pub struct GlesFrame<'frame> { span: EnteredSpan, } -impl fmt::Debug for GlesFrame<'_> { +impl fmt::Debug for GlesFrame<'_, '_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("GlesFrame") .field("renderer", &self.renderer) + .field("target", &self.target) .field("current_projection", &self.current_projection) .field("transform", &self.transform) .field("tex_program_override", &self.tex_program_override) @@ -320,7 +331,6 @@ impl fmt::Debug for GlesRenderer { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("GlesRenderer") .field("buffers", &self.buffers) - .field("target", &self.target) .field("extensions", &self.extensions) .field("capabilities", &self.capabilities) .field("tex_program", &self.tex_program) @@ -450,12 +460,10 @@ impl GlesRenderer { /// `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. /// - Shm buffers can be released after a successful import, without the texture handle becoming invalid. /// - Texture filtering starts with Linear-downscaling and Linear-upscaling. - /// - The renderer might use two-pass rendering internally to facilitate color space transformations. - /// As such it reserves any stencil buffer for internal use and makes no guarantee about previous framebuffer - /// contents being accessible during the lifetime of a `GlesFrame`. + /// - If OpenGL ES 3.0 is not available and the underlying [`EGLContext`] is shared, memory textures + /// will insert `glFinish`-calls into the pipeline. Consider not sharing contexts, if OpenGL ES 3 isn't available. pub unsafe fn with_capabilities( context: EGLContext, capabilities: impl IntoIterator<Item = Capability>, @@ -597,7 +605,6 @@ impl GlesRenderer { min_filter: TextureFilter::Linear, max_filter: TextureFilter::Linear, - target: None, buffers: Vec::new(), dmabuf_cache: std::collections::HashMap::new(), vertices: Vec::with_capacity(6 * 16), @@ -616,13 +623,57 @@ impl GlesRenderer { Ok(renderer) } + fn bind_texture<'a>(&mut self, texture: &'a GlesTexture) -> Result<GlesTarget<'a>, GlesError> { + unsafe { + self.egl.make_current()?; + } + + let bind = || { + let mut sync_lock = texture.0.sync.write().unwrap(); + let mut fbo = 0; + unsafe { + sync_lock.wait_for_all(&self.gl); + self.gl.GenFramebuffers(1, &mut fbo as *mut _); + self.gl.BindFramebuffer(ffi::FRAMEBUFFER, fbo); + self.gl.FramebufferTexture2D( + ffi::FRAMEBUFFER, + ffi::COLOR_ATTACHMENT0, + ffi::TEXTURE_2D, + texture.0.texture, + 0, + ); + let status = self.gl.CheckFramebufferStatus(ffi::FRAMEBUFFER); + self.gl.BindFramebuffer(ffi::FRAMEBUFFER, 0); + + if status != ffi::FRAMEBUFFER_COMPLETE { + self.gl.DeleteFramebuffers(1, &mut fbo as *mut _); + return Err(GlesError::FramebufferBindingError); + } + } + + Ok(GlesTarget(GlesTargetInternal::Texture { + texture: texture.clone(), + sync_lock, + destruction_callback_sender: self.destruction_callback_sender.clone(), + fbo, + })) + }; + + bind().inspect_err(|_| { + if let Err(err) = self.unbind() { + self.span.in_scope(|| warn!(?err, "Failed to unbind on err")); + } + }) + } + #[profiling::function] - pub(crate) fn make_current(&mut self) -> Result<(), MakeCurrentError> { - if let Some(target) = self.target.as_ref() { - target.make_current(&self.gl, &self.egl)?; - } else { - unsafe { self.egl.make_current()? }; + fn unbind(&mut self) -> Result<(), GlesError> { + unsafe { + self.egl.make_current()?; } + unsafe { self.gl.BindFramebuffer(ffi::FRAMEBUFFER, 0) }; + self.cleanup(); + self.egl.unbind()?; Ok(()) } @@ -682,13 +733,6 @@ impl GlesRenderer { } } -/// Warning: If your context only supports OpenGL ES 2.0 and -/// you are sharing EGLContexts, using [`import_shm_buffer`] -/// will insert a `glFinish()` call for every buffer import -/// to synchronize texture access. -/// -/// As a compositor developer consider not sharing -/// contexts, if OpenGL ES 3.0 is unavailable. #[cfg(feature = "wayland_frontend")] impl ImportMemWl for GlesRenderer { #[instrument(level = "trace", parent = &self.span, skip(self))] @@ -714,8 +758,6 @@ impl ImportMemWl for GlesRenderer { }); with_buffer_contents(buffer, |ptr, len, data| { - self.make_current()?; - let offset = data.offset; let width = data.width; let height = data.height; @@ -782,6 +824,7 @@ impl ImportMemWl for GlesRenderer { let mut sync_lock = texture.0.sync.write().unwrap(); unsafe { + self.egl.make_current()?; sync_lock.wait_for_all(&self.gl); self.gl.BindTexture(ffi::TEXTURE_2D, texture.0.texture); self.gl @@ -869,8 +912,6 @@ impl ImportMem for GlesRenderer { size: Size<i32, BufferCoord>, flipped: bool, ) -> Result<GlesTexture, GlesError> { - self.make_current()?; - if data.len() < (size.w * size.h) as usize * (get_bpp(format).ok_or(GlesError::UnsupportedPixelFormat(format))? / 8) @@ -902,6 +943,7 @@ impl ImportMem for GlesRenderer { let texture = GlesTexture(Arc::new({ let mut tex = 0; unsafe { + self.egl.make_current()?; self.gl.GenTextures(1, &mut tex); self.gl.BindTexture(ffi::TEXTURE_2D, tex); self.gl @@ -952,12 +994,10 @@ impl ImportMem for GlesRenderer { #[profiling::function] fn update_memory( &mut self, - texture: &<Self as Renderer>::TextureId, + texture: &Self::TextureId, data: &[u8], region: Rectangle<i32, BufferCoord>, - ) -> Result<(), <Self as Renderer>::Error> { - self.make_current()?; - + ) -> Result<(), Self::Error> { if texture.0.format.is_none() { return Err(GlesError::UnknownPixelFormat); } @@ -976,6 +1016,7 @@ impl ImportMem for GlesRenderer { let mut sync_lock = texture.0.sync.write().unwrap(); unsafe { + self.egl.make_current()?; sync_lock.wait_for_all(&self.gl); self.gl.BindTexture(ffi::TEXTURE_2D, texture.0.texture); self.gl @@ -1065,8 +1106,6 @@ impl ImportEgl for GlesRenderer { // clean up check if the buffer is still alive. For wl_drm the // is_alive check will always return true and the cache entry // will never be cleaned up. - self.make_current()?; - let egl = self .egl_reader .as_ref() @@ -1109,7 +1148,6 @@ impl ImportDma for GlesRenderer { return Err(GlesError::GLExtensionNotSupported(&["GL_OES_EGL_image"])); } - self.make_current()?; self.existing_dmabuf_texture(buffer)?.map(Ok).unwrap_or_else(|| { let is_external = !self.egl.dmabuf_render_formats().contains(&buffer.format()); let image = self @@ -1176,6 +1214,9 @@ impl GlesRenderer { is_external: bool, tex: Option<u32>, ) -> Result<u32, GlesError> { + unsafe { + self.egl.make_current()?; + } let tex = tex.unwrap_or_else(|| unsafe { let mut tex = 0; self.gl.GenTextures(1, &mut tex); @@ -1199,21 +1240,17 @@ impl GlesRenderer { impl ExportMem for GlesRenderer { type TextureMapping = GlesMapping; - #[instrument(level = "trace", parent = &self.span, skip(self))] + #[instrument(level = "trace", parent = &self.span, skip(self, target))] #[profiling::function] fn copy_framebuffer( &mut self, + target: &GlesTarget<'_>, region: Rectangle<i32, BufferCoord>, fourcc: Fourcc, ) -> Result<Self::TextureMapping, Self::Error> { - self.make_current()?; + target.0.make_current(&self.gl, &self.egl)?; - let (_, has_alpha) = self - .target - .as_ref() - .ok_or(GlesError::UnknownPixelFormat)? - .format() - .ok_or(GlesError::UnknownPixelFormat)?; + let (_, has_alpha) = target.0.format().ok_or(GlesError::UnknownPixelFormat)?; let (_, format, layout) = fourcc_to_gl_formats(fourcc).ok_or(GlesError::UnknownPixelFormat)?; let mut pbo = 0; @@ -1225,13 +1262,12 @@ impl ExportMem for GlesRenderer { let size = (region.size.w * region.size.h * bpp as i32) as isize; self.gl .BufferData(ffi::PIXEL_PACK_BUFFER, size, ptr::null(), ffi::STREAM_READ); - self.gl.ReadBuffer( - if matches!(self.target.as_ref(), None | Some(GlesTarget::Surface { .. })) { + self.gl + .ReadBuffer(if matches!(target.0, GlesTargetInternal::Surface { .. }) { ffi::BACK } else { ffi::COLOR_ATTACHMENT0 - }, - ); + }); self.gl.ReadPixels( region.loc.x, region.loc.y, @@ -1262,17 +1298,8 @@ impl ExportMem for GlesRenderer { } fn can_read_texture(&mut self, texture: &Self::TextureId) -> Result<bool, GlesError> { - let old_target = self.target.take(); - // if we can't bind the texture, we can't read it - let res = self.bind(texture.clone()).is_ok(); - - // restore - self.unbind()?; - self.target = old_target; - self.make_current()?; - - Ok(res) + Ok(self.bind_texture(texture).is_ok()) } #[instrument(level = "trace", parent = &self.span, skip(self))] @@ -1284,8 +1311,8 @@ impl ExportMem for GlesRenderer { fourcc: Fourcc, ) -> Result<Self::TextureMapping, Self::Error> { let mut pbo = 0; - let old_target = self.target.take(); - self.bind(texture.clone())?; + let target = self.bind_texture(texture)?; + target.0.make_current(&self.gl, &self.egl)?; let (_, format, layout) = fourcc_to_gl_formats(fourcc).ok_or(GlesError::UnknownPixelFormat)?; let bpp = gl_bpp(format, layout).expect("We check the format before") / 8; @@ -1315,11 +1342,6 @@ impl ExportMem for GlesRenderer { self.gl.GetError() }; - // restore old framebuffer - self.unbind()?; - self.target = old_target; - self.make_current()?; - match err { ffi::NO_ERROR => Ok(GlesMapping { pbo, @@ -1341,7 +1363,10 @@ impl ExportMem for GlesRenderer { &mut self, texture_mapping: &'a Self::TextureMapping, ) -> Result<&'a [u8], Self::Error> { - self.make_current()?; + unsafe { + self.egl.make_current()?; + } + let size = texture_mapping.size(); let len = size.w * size.h * 4; @@ -1369,53 +1394,36 @@ impl ExportMem for GlesRenderer { } } -impl Bind<Rc<EGLSurface>> for GlesRenderer { - #[instrument(level = "trace", parent = &self.span, skip(self))] - #[profiling::function] - fn bind(&mut self, surface: Rc<EGLSurface>) -> Result<(), GlesError> { - unsafe { - self.egl.make_current()?; - } - - self.target = Some(GlesTarget::Surface { - surface: surface.clone(), - }); - let res = self.make_current(); - if res.is_err() { - let _ = self.unbind(); - } - res?; - - Ok(()) +impl Bind<EGLSurface> for GlesRenderer { + fn bind<'a>(&mut self, surface: &'a mut EGLSurface) -> Result<GlesTarget<'a>, GlesError> { + Ok(GlesTarget(GlesTargetInternal::Surface { surface })) } } impl Bind<Dmabuf> for GlesRenderer { - #[instrument(level = "trace", parent = &self.span, skip(self))] - #[profiling::function] - fn bind(&mut self, dmabuf: Dmabuf) -> Result<(), GlesError> { + fn bind<'a>(&mut self, dmabuf: &'a mut Dmabuf) -> Result<GlesTarget<'a>, GlesError> { unsafe { self.egl.make_current()?; } - let bind = || { - let (buf, dmabuf) = self + let mut bind = |dmabuf: &'a mut Dmabuf| { + let buf = self .buffers .iter_mut() .find(|buffer| { if let Some(dma) = buffer.dmabuf.upgrade() { - dma == dmabuf + dma == *dmabuf } else { false } }) - .map(|buf| Ok((buf.clone(), buf.dmabuf.upgrade().unwrap()))) + .map(|buf| Ok(buf.clone())) .unwrap_or_else(|| { trace!("Creating EGLImage for Dmabuf: {:?}", dmabuf); let image = self .egl .display() - .create_image_from_dmabuf(&dmabuf) + .create_image_from_dmabuf(dmabuf) .map_err(GlesError::BindBufferEGLError)?; unsafe { @@ -1439,7 +1447,9 @@ impl Bind<Dmabuf> for GlesRenderer { self.gl.BindFramebuffer(ffi::FRAMEBUFFER, 0); if status != ffi::FRAMEBUFFER_COMPLETE { - //TODO wrap image and drop here + self.gl.DeleteFramebuffers(1, &mut fbo as *mut _); + self.gl.DeleteRenderbuffers(1, &mut rbo as *mut _); + ffi_egl::DestroyImageKHR(**self.egl.display().get_display_handle(), image); return Err(GlesError::FramebufferBindingError); } let buf = GlesBuffer { @@ -1451,20 +1461,18 @@ impl Bind<Dmabuf> for GlesRenderer { self.buffers.push(buf.clone()); - Ok((buf, dmabuf)) + Ok(buf) } })?; - self.target = Some(GlesTarget::Image { buf, dmabuf }); - std::result::Result::<(), GlesError>::Ok(()) + Ok(GlesTarget(GlesTargetInternal::Image { buf, dmabuf })) }; - let res = bind(); - if res.is_err() { - let _ = self.unbind(); - } - res?; - self.make_current()?; - Ok(()) + + bind(dmabuf).inspect_err(|_| { + if let Err(err) = self.unbind() { + self.span.in_scope(|| warn!(?err, "Failed to unbind on err")); + } + }) } fn supported_formats(&self) -> Option<FormatSet> { @@ -1473,29 +1481,32 @@ impl Bind<Dmabuf> for GlesRenderer { } impl Bind<GlesTexture> for GlesRenderer { - #[instrument(level = "trace", parent = &self.span, skip(self))] - #[profiling::function] - fn bind(&mut self, texture: GlesTexture) -> Result<(), GlesError> { + fn bind<'a>(&mut self, texture: &'a mut GlesTexture) -> Result<GlesTarget<'a>, GlesError> { + self.bind_texture(texture) + } +} + +impl Bind<GlesRenderbuffer> for GlesRenderer { + fn bind<'a>(&mut self, renderbuffer: &'a mut GlesRenderbuffer) -> Result<GlesTarget<'a>, GlesError> { unsafe { self.egl.make_current()?; } - let bind = || { + let bind = |renderbuffer: &'a mut GlesRenderbuffer| { let mut fbo = 0; unsafe { - // TODO: we should keep the lock, while the Target is active - texture.0.sync.read().unwrap().wait_for_upload(&self.gl); self.gl.GenFramebuffers(1, &mut fbo as *mut _); self.gl.BindFramebuffer(ffi::FRAMEBUFFER, fbo); - self.gl.FramebufferTexture2D( + self.gl.BindRenderbuffer(ffi::RENDERBUFFER, renderbuffer.0.rbo); + self.gl.FramebufferRenderbuffer( ffi::FRAMEBUFFER, ffi::COLOR_ATTACHMENT0, - ffi::TEXTURE_2D, - texture.0.texture, - 0, + ffi::RENDERBUFFER, + renderbuffer.0.rbo, ); let status = self.gl.CheckFramebufferStatus(ffi::FRAMEBUFFER); self.gl.BindFramebuffer(ffi::FRAMEBUFFER, 0); + self.gl.BindRenderbuffer(ffi::RENDERBUFFER, 0); if status != ffi::FRAMEBUFFER_COMPLETE { self.gl.DeleteFramebuffers(1, &mut fbo as *mut _); @@ -1503,21 +1514,17 @@ impl Bind<GlesTexture> for GlesRenderer { } } - self.target = Some(GlesTarget::Texture { - texture, - destruction_callback_sender: self.destruction_callback_sender.clone(), + Ok(GlesTarget(GlesTargetInternal::Renderbuffer { + buf: renderbuffer, fbo, - }); - Ok(()) + })) }; - let res = bind(); - if res.is_err() { - let _ = self.unbind(); - } - res?; - self.make_current()?; - Ok(()) + bind(renderbuffer).inspect_err(|_| { + if let Err(err) = self.unbind() { + self.span.in_scope(|| warn!(?err, "Failed to unbind on err")); + } + }) } } @@ -1529,8 +1536,6 @@ impl Offscreen<GlesTexture> for GlesRenderer { format: Fourcc, size: Size<i32, BufferCoord>, ) -> Result<GlesTexture, GlesError> { - self.make_current()?; - let has_alpha = has_alpha(format); let (internal, format, layout) = fourcc_to_gl_formats(format).ok_or(GlesError::UnsupportedPixelFormat(format))?; @@ -1541,6 +1546,7 @@ impl Offscreen<GlesTexture> for GlesRenderer { } let tex = unsafe { + self.egl.make_current()?; let mut tex = 0; self.gl.GenTextures(1, &mut tex); self.gl.BindTexture(ffi::TEXTURE_2D, tex); @@ -1562,44 +1568,6 @@ impl Offscreen<GlesTexture> for GlesRenderer { } } -impl Bind<GlesRenderbuffer> for GlesRenderer { - #[instrument(level = "trace", parent = &self.span, skip(self))] - #[profiling::function] - fn bind(&mut self, renderbuffer: GlesRenderbuffer) -> Result<(), GlesError> { - self.unbind()?; - self.make_current()?; - - let mut fbo = 0; - unsafe { - self.gl.GenFramebuffers(1, &mut fbo as *mut _); - self.gl.BindFramebuffer(ffi::FRAMEBUFFER, fbo); - self.gl.BindRenderbuffer(ffi::RENDERBUFFER, renderbuffer.0.rbo); - self.gl.FramebufferRenderbuffer( - ffi::FRAMEBUFFER, - ffi::COLOR_ATTACHMENT0, - ffi::RENDERBUFFER, - renderbuffer.0.rbo, - ); - let status = self.gl.CheckFramebufferStatus(ffi::FRAMEBUFFER); - self.gl.BindFramebuffer(ffi::FRAMEBUFFER, 0); - self.gl.BindRenderbuffer(ffi::RENDERBUFFER, 0); - - if status != ffi::FRAMEBUFFER_COMPLETE { - self.gl.DeleteFramebuffers(1, &mut fbo as *mut _); - return Err(GlesError::FramebufferBindingError); - } - } - - self.target = Some(GlesTarget::Renderbuffer { - buf: renderbuffer, - fbo, - }); - self.make_current()?; - - Ok(()) - } -} - impl Offscreen<GlesRenderbuffer> for GlesRenderer { #[instrument(level = "trace", parent = &self.span, skip(self))] #[profiling::function] @@ -1611,8 +1579,6 @@ impl Offscreen<GlesRenderbuffer> for GlesRenderer { if !self.capabilities.contains(&Capability::Renderbuffer) { return Err(GlesError::UnsupportedPixelFormat(format)); } - self.make_current()?; - let has_alpha = has_alpha(format); let (internal, _, _) = fourcc_to_gl_formats(format).ok_or(GlesError::UnsupportedPixelFormat(format))?; @@ -1622,6 +1588,8 @@ impl Offscreen<GlesRenderbuffer> for GlesRenderer { } unsafe { + self.egl.make_current()?; + let mut rbo = 0; self.gl.GenRenderbuffers(1, &mut rbo); self.gl.BindRenderbuffer(ffi::RENDERBUFFER, rbo); @@ -1640,62 +1608,13 @@ impl Offscreen<GlesRenderbuffer> for GlesRenderer { } } -impl<Target> Blit<Target> for GlesRenderer -where - Self: Bind<Target>, -{ - #[instrument(level = "trace", parent = &self.span, skip(self, to))] - #[profiling::function] - fn blit_to( - &mut self, - to: Target, - src: Rectangle<i32, Physical>, - dst: Rectangle<i32, Physical>, - filter: TextureFilter, - ) -> Result<(), GlesError> { - let src_target = self.target.take().ok_or(GlesError::BlitError)?; - self.bind(to)?; - let dst_target = self.target.take().unwrap(); - self.unbind()?; - - let result = self.blit(&src_target, &dst_target, src, dst, filter); - - self.target = Some(src_target); - self.make_current()?; - - result - } - - #[instrument(level = "trace", parent = &self.span, skip(self, from))] - #[profiling::function] - fn blit_from( - &mut self, - from: Target, - src: Rectangle<i32, Physical>, - dst: Rectangle<i32, Physical>, - filter: TextureFilter, - ) -> Result<(), GlesError> { - let dst_target = self.target.take().ok_or(GlesError::BlitError)?; - self.bind(from)?; - let src_target = self.target.take().unwrap(); - self.unbind()?; - - let result = self.blit(&src_target, &dst_target, src, dst, filter); - - self.unbind()?; - self.target = Some(dst_target); - self.make_current()?; - - result - } -} - -impl GlesRenderer { +impl Blit for GlesRenderer { + #[instrument(level = "trace", parent = &self.span, skip(self, src_target, dst_target))] #[profiling::function] fn blit( &mut self, - src_target: &GlesTarget, - dst_target: &GlesTarget, + src_target: &GlesTarget<'_>, + dst_target: &mut GlesTarget<'_>, src: Rectangle<i32, Physical>, dst: Rectangle<i32, Physical>, filter: TextureFilter, @@ -1705,14 +1624,17 @@ impl GlesRenderer { return Err(GlesError::GLVersionNotSupported(version::GLES_3_0)); } - match (src_target, dst_target) { - (GlesTarget::Surface { surface: src, .. }, GlesTarget::Surface { surface: dst, .. }) => unsafe { + match (&src_target.0, &dst_target.0) { + ( + GlesTargetInternal::Surface { surface: src, .. }, + GlesTargetInternal::Surface { surface: dst, .. }, + ) => unsafe { self.egl.make_current_with_draw_and_read_surface(dst, src)?; }, - (GlesTarget::Surface { surface: src, .. }, _) => unsafe { + (GlesTargetInternal::Surface { surface: src, .. }, _) => unsafe { self.egl.make_current_with_surface(src)?; }, - (_, GlesTarget::Surface { surface: dst, .. }) => unsafe { + (_, GlesTargetInternal::Surface { surface: dst, .. }) => unsafe { self.egl.make_current_with_surface(dst)?; }, (_, _) => unsafe { @@ -1720,26 +1642,26 @@ impl GlesRenderer { }, } - match src_target { - GlesTarget::Image { ref buf, .. } => unsafe { + match &src_target.0 { + GlesTargetInternal::Image { ref buf, .. } => unsafe { self.gl.BindFramebuffer(ffi::READ_FRAMEBUFFER, buf.fbo) }, - GlesTarget::Texture { ref fbo, .. } => unsafe { + GlesTargetInternal::Texture { ref fbo, .. } => unsafe { self.gl.BindFramebuffer(ffi::READ_FRAMEBUFFER, *fbo) }, - GlesTarget::Renderbuffer { ref fbo, .. } => unsafe { + GlesTargetInternal::Renderbuffer { ref fbo, .. } => unsafe { self.gl.BindFramebuffer(ffi::READ_FRAMEBUFFER, *fbo) }, _ => {} // Note: The only target missing is `Surface` and handled above } - match dst_target { - GlesTarget::Image { ref buf, .. } => unsafe { + match &dst_target.0 { + GlesTargetInternal::Image { ref buf, .. } => unsafe { self.gl.BindFramebuffer(ffi::DRAW_FRAMEBUFFER, buf.fbo) }, - GlesTarget::Texture { ref fbo, .. } => unsafe { + GlesTargetInternal::Texture { ref fbo, .. } => unsafe { self.gl.BindFramebuffer(ffi::DRAW_FRAMEBUFFER, *fbo) }, - GlesTarget::Renderbuffer { ref fbo, .. } => unsafe { + GlesTargetInternal::Renderbuffer { ref fbo, .. } => unsafe { self.gl.BindFramebuffer(ffi::DRAW_FRAMEBUFFER, *fbo) }, _ => {} // Note: The only target missing is `Surface` and handled above @@ -1779,20 +1701,6 @@ impl GlesRenderer { } } -impl Unbind for GlesRenderer { - #[profiling::function] - fn unbind(&mut self) -> Result<(), <Self as Renderer>::Error> { - unsafe { - self.egl.make_current()?; - } - unsafe { self.gl.BindFramebuffer(ffi::FRAMEBUFFER, 0) }; - self.target = None; - self.cleanup(); - self.egl.unbind()?; - Ok(()) - } -} - impl Drop for GlesRenderer { fn drop(&mut self) { let _guard = self.span.enter(); @@ -1844,7 +1752,9 @@ impl GlesRenderer { where F: FnOnce(&ffi::Gles2) -> R, { - self.make_current()?; + unsafe { + self.egl.make_current()?; + } Ok(func(&self.gl)) } @@ -1874,7 +1784,9 @@ impl GlesRenderer { src: impl AsRef<str>, additional_uniforms: &[UniformName<'_>], ) -> Result<GlesPixelProgram, GlesError> { - self.make_current()?; + unsafe { + self.egl.make_current()?; + } let shader = format!("#version 100\n{}", src.as_ref()); let program = unsafe { link_program(&self.gl, shaders::VERTEX_SHADER, &shader)? }; @@ -2001,7 +1913,9 @@ impl GlesRenderer { shader: impl AsRef<str>, additional_uniforms: &[UniformName<'_>], ) -> Result<GlesTexProgram, GlesError> { - self.make_current()?; + unsafe { + self.egl.make_current()?; + } unsafe { texture_program( @@ -2014,7 +1928,7 @@ impl GlesRenderer { } } -impl GlesFrame<'_> { +impl GlesFrame<'_, '_> { /// Run custom code in the GL context owned by this renderer. /// /// The OpenGL state of the renderer is considered an implementation detail @@ -2032,11 +1946,17 @@ impl GlesFrame<'_> { } } -impl Renderer for GlesRenderer { +impl RendererSuper for GlesRenderer { type Error = GlesError; type TextureId = GlesTexture; - type Frame<'frame> = GlesFrame<'frame>; + type Framebuffer<'buffer> = GlesTarget<'buffer>; + type Frame<'frame, 'buffer> + = GlesFrame<'frame, 'buffer> + where + 'buffer: 'frame; +} +impl Renderer for GlesRenderer { fn id(&self) -> usize { self.egl.user_data().get::<RendererId>().unwrap().0 } @@ -2050,13 +1970,25 @@ impl Renderer for GlesRenderer { Ok(()) } + fn set_debug_flags(&mut self, flags: DebugFlags) { + self.debug_flags = flags; + } + + fn debug_flags(&self) -> DebugFlags { + self.debug_flags + } + #[profiling::function] - fn render( - &mut self, + fn render<'frame, 'buffer>( + &'frame mut self, + target: &'frame mut GlesTarget<'buffer>, mut output_size: Size<i32, Physical>, transform: Transform, - ) -> Result<GlesFrame<'_>, Self::Error> { - self.make_current()?; + ) -> Result<GlesFrame<'frame, 'buffer>, GlesError> + where + 'buffer: 'frame, + { + target.0.make_current(&self.gl, &self.egl)?; unsafe { self.gl.Viewport(0, 0, output_size.w, output_size.h); @@ -2098,6 +2030,7 @@ impl Renderer for GlesRenderer { Ok(GlesFrame { renderer: self, + target, // output transformation passed in by the user current_projection, transform, @@ -2109,17 +2042,11 @@ impl Renderer for GlesRenderer { }) } - fn set_debug_flags(&mut self, flags: DebugFlags) { - self.debug_flags = flags; - } - - fn debug_flags(&self) -> DebugFlags { - self.debug_flags - } - #[profiling::function] fn wait(&mut self, sync: &super::sync::SyncPoint) -> Result<(), Self::Error> { - self.make_current()?; + unsafe { + self.egl.make_current()?; + } let display = self.egl_context().display(); @@ -2152,7 +2079,9 @@ impl Renderer for GlesRenderer { #[profiling::function] fn cleanup_texture_cache(&mut self) -> Result<(), Self::Error> { - self.make_current()?; + unsafe { + self.egl.make_current()?; + } self.cleanup(); Ok(()) } @@ -2213,7 +2142,7 @@ static OUTPUT_VERTS: [ffi::types::GLfloat; 8] = [ 1.0, -1.0, // bottom left ]; -impl Frame for GlesFrame<'_> { +impl Frame for GlesFrame<'_, '_> { type TextureId = GlesTexture; type Error = GlesError; @@ -2313,7 +2242,7 @@ impl Frame for GlesFrame<'_> { } } -impl GlesFrame<'_> { +impl GlesFrame<'_, '_> { #[profiling::function] fn finish_internal(&mut self) -> Result<SyncPoint, GlesError> { let _guard = self.span.enter(); @@ -2327,6 +2256,10 @@ impl GlesFrame<'_> { self.renderer.gl.Disable(ffi::BLEND); } + if let GlesTargetInternal::Texture { sync_lock, .. } = &mut self.target.0 { + sync_lock.update_write(&self.renderer.gl); + } + // delayed destruction until the next frame rendering. self.renderer.cleanup(); @@ -2970,7 +2903,7 @@ impl GlesFrame<'_> { } } -impl Drop for GlesFrame<'_> { +impl Drop for GlesFrame<'_, '_> { fn drop(&mut self) { match self.finish_internal() { Ok(sync) => { diff --git a/src/backend/renderer/gles/texture.rs b/src/backend/renderer/gles/texture.rs index a88526444524..3450c01daf3d 100644 --- a/src/backend/renderer/gles/texture.rs +++ b/src/backend/renderer/gles/texture.rs @@ -93,8 +93,8 @@ impl TextureSync { pub(super) fn wait_for_all(&mut self, gl: &Gles2) { unsafe { - wait_for_syncpoint(&mut self.read_sync.get_mut().unwrap(), gl); - wait_for_syncpoint(&mut self.write_sync.get_mut().unwrap(), gl); + wait_for_syncpoint(self.read_sync.get_mut().unwrap(), gl); + wait_for_syncpoint(self.write_sync.get_mut().unwrap(), gl); } } diff --git a/src/backend/renderer/glow.rs b/src/backend/renderer/glow.rs index 205ff34ba3e0..9541a66fae0a 100644 --- a/src/backend/renderer/glow.rs +++ b/src/backend/renderer/glow.rs @@ -17,7 +17,7 @@ use crate::{ element::UnderlyingStorage, gles::{element::*, *}, sync, Bind, Blit, Color32F, DebugFlags, ExportMem, ImportDma, ImportMem, Offscreen, Renderer, - TextureFilter, Unbind, + RendererSuper, TextureFilter, }, }, utils::{Buffer as BufferCoord, Physical, Rectangle, Size, Transform}, @@ -45,8 +45,8 @@ pub struct GlowRenderer { /// [`Frame`] implementation of a [`GlowRenderer`]. /// /// Leaking the frame will cause the same problems as leaking a [`GlesFrame`]. -pub struct GlowFrame<'a> { - frame: Option<GlesFrame<'a>>, +pub struct GlowFrame<'frame, 'buffer> { + frame: Option<GlesFrame<'frame, 'buffer>>, glow: Arc<Context>, } @@ -129,12 +129,14 @@ impl GlowRenderer { where F: FnOnce(&Arc<Context>) -> R, { - self.gl.make_current()?; + unsafe { + self.gl.egl_context().make_current()?; + } Ok(func(&self.glow)) } } -impl GlowFrame<'_> { +impl GlowFrame<'_, '_> { /// Run custom code in the GL context owned by this renderer. /// /// The OpenGL state of the renderer is considered an implementation detail @@ -156,9 +158,9 @@ impl GlowFrame<'_> { // just as `TryFrom<GlesRenderer, Error=GlesError> for GlowRenderer` impl From<GlesRenderer> for GlowRenderer { #[inline] - fn from(mut renderer: GlesRenderer) -> GlowRenderer { + fn from(renderer: GlesRenderer) -> GlowRenderer { let glow = unsafe { - renderer.make_current().unwrap(); + renderer.egl_context().make_current().unwrap(); Context::from_loader_function(|s| crate::backend::egl::get_proc_address(s) as *const _) }; @@ -183,25 +185,32 @@ impl BorrowMut<GlesRenderer> for GlowRenderer { } } -impl<'frame> Borrow<GlesFrame<'frame>> for GlowFrame<'frame> { +impl<'frame, 'buffer> Borrow<GlesFrame<'frame, 'buffer>> for GlowFrame<'frame, 'buffer> { #[inline] - fn borrow(&self) -> &GlesFrame<'frame> { + fn borrow(&self) -> &GlesFrame<'frame, 'buffer> { self.frame.as_ref().unwrap() } } -impl<'frame> BorrowMut<GlesFrame<'frame>> for GlowFrame<'frame> { +impl<'frame, 'buffer> BorrowMut<GlesFrame<'frame, 'buffer>> for GlowFrame<'frame, 'buffer> { #[inline] - fn borrow_mut(&mut self) -> &mut GlesFrame<'frame> { + fn borrow_mut(&mut self) -> &mut GlesFrame<'frame, 'buffer> { self.frame.as_mut().unwrap() } } -impl Renderer for GlowRenderer { +impl RendererSuper for GlowRenderer { type Error = GlesError; type TextureId = GlesTexture; - type Frame<'frame> = GlowFrame<'frame>; + type Frame<'frame, 'buffer> + = GlowFrame<'frame, 'buffer> + where + 'buffer: 'frame, + Self: 'frame; + type Framebuffer<'buffer> = GlesTarget<'buffer>; +} +impl Renderer for GlowRenderer { fn id(&self) -> usize { self.gl.id() } @@ -221,13 +230,17 @@ impl Renderer for GlowRenderer { } #[profiling::function] - fn render( - &mut self, + fn render<'frame, 'buffer>( + &'frame mut self, + target: &'frame mut GlesTarget<'buffer>, output_size: Size<i32, Physical>, transform: Transform, - ) -> Result<GlowFrame<'_>, Self::Error> { + ) -> Result<GlowFrame<'frame, 'buffer>, Self::Error> + where + 'buffer: 'frame, + { let glow = self.glow.clone(); - let frame = self.gl.render(output_size, transform)?; + let frame = self.gl.render(target, output_size, transform)?; Ok(GlowFrame { frame: Some(frame), glow, @@ -245,7 +258,7 @@ impl Renderer for GlowRenderer { } } -impl Frame for GlowFrame<'_> { +impl Frame for GlowFrame<'_, '_> { type TextureId = GlesTexture; type Error = GlesError; @@ -330,7 +343,7 @@ impl Frame for GlowFrame<'_> { } } -impl GlowFrame<'_> { +impl GlowFrame<'_, '_> { #[profiling::function] fn finish_internal(&mut self) -> Result<sync::SyncPoint, GlesError> { if let Some(frame) = self.frame.take() { @@ -341,7 +354,7 @@ impl GlowFrame<'_> { } } -impl Drop for GlowFrame<'_> { +impl Drop for GlowFrame<'_, '_> { fn drop(&mut self) { if let Err(err) = self.finish_internal() { warn!("Ignored error finishing GlowFrame on drop: {}", err); @@ -381,10 +394,10 @@ impl ImportMem for GlowRenderer { #[profiling::function] fn update_memory( &mut self, - texture: &<Self as Renderer>::TextureId, + texture: &Self::TextureId, data: &[u8], region: Rectangle<i32, BufferCoord>, - ) -> Result<(), <Self as Renderer>::Error> { + ) -> Result<(), Self::Error> { self.gl.update_memory(texture, data, region) } @@ -451,10 +464,11 @@ impl ExportMem for GlowRenderer { #[profiling::function] fn copy_framebuffer( &mut self, + from: &GlesTarget<'_>, region: Rectangle<i32, BufferCoord>, format: Fourcc, ) -> Result<Self::TextureMapping, Self::Error> { - self.gl.copy_framebuffer(region, format) + self.gl.copy_framebuffer(from, region, format) } #[profiling::function] @@ -485,7 +499,7 @@ where GlesRenderer: Bind<T>, { #[profiling::function] - fn bind(&mut self, target: T) -> Result<(), GlesError> { + fn bind<'a>(&mut self, target: &'a mut T) -> Result<GlesTarget<'a>, GlesError> { self.gl.bind(target) } fn supported_formats(&self) -> Option<FormatSet> { @@ -503,36 +517,17 @@ where } } -impl<Target> Blit<Target> for GlowRenderer -where - GlesRenderer: Blit<Target>, -{ +impl Blit for GlowRenderer { #[profiling::function] - fn blit_to( + fn blit( &mut self, - to: Target, + from: &GlesTarget<'_>, + to: &mut GlesTarget<'_>, src: Rectangle<i32, Physical>, dst: Rectangle<i32, Physical>, filter: TextureFilter, ) -> Result<(), GlesError> { - self.gl.blit_to(to, src, dst, filter) - } - - #[profiling::function] - fn blit_from( - &mut self, - from: Target, - src: Rectangle<i32, Physical>, - dst: Rectangle<i32, Physical>, - filter: TextureFilter, - ) -> Result<(), GlesError> { - self.gl.blit_from(from, src, dst, filter) - } -} - -impl Unbind for GlowRenderer { - fn unbind(&mut self) -> Result<(), <Self as Renderer>::Error> { - self.gl.unbind() + self.gl.blit(from, to, src, dst, filter) } } @@ -540,7 +535,7 @@ impl RenderElement<GlowRenderer> for PixelShaderElement { #[profiling::function] fn draw( &self, - frame: &mut GlowFrame<'_>, + frame: &mut GlowFrame<'_, '_>, src: Rectangle<f64, BufferCoord>, dst: Rectangle<i32, Physical>, damage: &[Rectangle<i32, Physical>], @@ -558,7 +553,7 @@ impl RenderElement<GlowRenderer> for TextureShaderElement { #[profiling::function] fn draw( &self, - frame: &mut GlowFrame<'_>, + frame: &mut GlowFrame<'_, '_>, src: Rectangle<f64, BufferCoord>, dst: Rectangle<i32, Physical>, damage: &[Rectangle<i32, Physical>], diff --git a/src/backend/renderer/mod.rs b/src/backend/renderer/mod.rs index 7318acd506c7..76dcf506de6b 100644 --- a/src/backend/renderer/mod.rs +++ b/src/backend/renderer/mod.rs @@ -54,7 +54,9 @@ pub mod damage; pub mod sync; -#[cfg(feature = "renderer_test")] +// Note: This doesn't fully work yet due to <https://github.com/rust-lang/rust/issues/67295>. +// Use `--features renderer_test` when running doc tests manually. +#[cfg(any(feature = "renderer_test", test, doctest))] pub mod test; #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] @@ -103,27 +105,23 @@ impl From<wayland_server::protocol::wl_output::Transform> for Transform { } /// Abstraction for Renderers, that can render into different targets -pub trait Bind<Target>: Unbind { - /// Bind a given rendering target, which will contain the rendering results until `unbind` is called. +pub trait Bind<Target>: Renderer { + /// Initialize a framebuffer with a given rendering target. /// - /// Binding to target, while another one is already bound, is rendering defined. - /// Some renderers might happily replace the current target, while other might drop the call - /// or throw an error. - fn bind(&mut self, target: Target) -> Result<(), <Self as Renderer>::Error>; + /// The `output_size` specifies the dimensions of the display **before** the `dst_transform` is + /// applied. + /// + /// This function *may* error, if: + /// - The given dimensions are unsupported (too large) for this renderer + /// - The given Transformation is not supported by the renderer (`Transform::Normal` is always supported). + fn bind<'a>(&mut self, target: &'a mut Target) -> Result<Self::Framebuffer<'a>, Self::Error>; + /// Supported pixel formats for given targets, if applicable. fn supported_formats(&self) -> Option<FormatSet> { None } } -/// Functionality to unbind the current rendering target -pub trait Unbind: Renderer { - /// Unbind the current rendering target. - /// - /// May fall back to a default target, if defined by the implementation. - fn unbind(&mut self) -> Result<(), <Self as Renderer>::Error>; -} - /// A two dimensional texture pub trait Texture: fmt::Debug { /// Size of the texture plane @@ -263,17 +261,26 @@ bitflags::bitflags! { const TINT = 0b00000001; } } -/// Abstraction of commonly used rendering operations for compositors. -pub trait Renderer: fmt::Debug { + +/// Workaround for <https://github.com/rust-lang/rust/issues/87479>, please look at [`Renderer`] instead. +pub trait RendererSuper: fmt::Debug { /// Error type returned by the rendering operations of this renderer. type Error: Error; /// Texture Handle type used by this renderer. type TextureId: Texture; + /// Framebuffer to draw onto + type Framebuffer<'buffer>; /// Type representing a currently in-progress frame during the [`Renderer::render`]-call - type Frame<'frame>: Frame<Error = Self::Error, TextureId = Self::TextureId> + 'frame + type Frame<'frame, 'buffer>: Frame<Error = Self::Error, TextureId = Self::TextureId> where + 'buffer: 'frame, Self: 'frame; +} +/// Abstraction of commonly used rendering operations for compositors. +/// +/// *Note*: Associated types are defined in [`RendererSuper`]. +pub trait Renderer: RendererSuper { /// Returns an id, that is unique to all renderers, that can use /// `TextureId`s originating from any of these renderers. fn id(&self) -> usize; @@ -288,7 +295,7 @@ pub trait Renderer: fmt::Debug { /// Returns the current enabled [`DebugFlags`] fn debug_flags(&self) -> DebugFlags; - /// Initialize a rendering context on the current rendering target with given dimensions and transformation. + /// Initialize a rendering context on the provided framebuffer with given dimensions and transformation. /// /// The `output_size` specifies the dimensions of the display **before** the `dst_transform` is /// applied. @@ -296,13 +303,14 @@ pub trait Renderer: fmt::Debug { /// This function *may* error, if: /// - The given dimensions are unsupported (too large) for this renderer /// - The given Transformation is not supported by the renderer (`Transform::Normal` is always supported). - /// - This renderer implements `Bind`, no target was bound *and* has no default target. - /// - (Renderers not implementing `Bind` always have a default target.) - fn render( - &mut self, + fn render<'frame, 'buffer>( + &'frame mut self, + framebuffer: &'frame mut Self::Framebuffer<'buffer>, output_size: Size<i32, Physical>, dst_transform: Transform, - ) -> Result<Self::Frame<'_>, Self::Error>; + ) -> Result<Self::Frame<'frame, 'buffer>, Self::Error> + where + 'buffer: 'frame; /// Wait for a [`SyncPoint`](sync::SyncPoint) to be signaled fn wait(&mut self, sync: &sync::SyncPoint) -> Result<(), Self::Error>; @@ -329,11 +337,7 @@ pub trait Offscreen<Target>: Renderer + Bind<Target> { /// - The maximum amount of framebuffers for this renderer would be exceeded /// - The format is not supported to be rendered into /// - The size is too large for a framebuffer - fn create_buffer( - &mut self, - format: Fourcc, - size: Size<i32, BufferCoord>, - ) -> Result<Target, <Self as Renderer>::Error>; + fn create_buffer(&mut self, format: Fourcc, size: Size<i32, BufferCoord>) -> Result<Target, Self::Error>; } /// Trait for Renderers supporting importing wl_buffers using shared memory. @@ -359,7 +363,7 @@ pub trait ImportMemWl: ImportMem { buffer: &wl_buffer::WlBuffer, surface: Option<&crate::wayland::compositor::SurfaceData>, damage: &[Rectangle<i32, BufferCoord>], - ) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>; + ) -> Result<Self::TextureId, Self::Error>; /// Returns supported formats for shared memory buffers. /// @@ -393,7 +397,7 @@ pub trait ImportMem: Renderer { format: Fourcc, size: Size<i32, BufferCoord>, flipped: bool, - ) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>; + ) -> Result<Self::TextureId, Self::Error>; /// Update a portion of a given chunk of memory into an existing texture. /// @@ -411,10 +415,10 @@ pub trait ImportMem: Renderer { /// to support resizing the original texture. fn update_memory( &mut self, - texture: &<Self as Renderer>::TextureId, + texture: &Self::TextureId, data: &[u8], region: Rectangle<i32, BufferCoord>, - ) -> Result<(), <Self as Renderer>::Error>; + ) -> Result<(), Self::Error>; /// Returns supported formats for memory imports. fn mem_formats(&self) -> Box<dyn Iterator<Item = Fourcc>>; @@ -472,7 +476,7 @@ pub trait ImportEgl: Renderer { buffer: &wl_buffer::WlBuffer, surface: Option<&crate::wayland::compositor::SurfaceData>, damage: &[Rectangle<i32, BufferCoord>], - ) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>; + ) -> Result<Self::TextureId, Self::Error>; } #[cfg(feature = "wayland_frontend")] @@ -494,7 +498,7 @@ pub trait ImportDmaWl: ImportDma { buffer: &wl_buffer::WlBuffer, _surface: Option<&crate::wayland::compositor::SurfaceData>, damage: &[Rectangle<i32, BufferCoord>], - ) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error> { + ) -> Result<Self::TextureId, Self::Error> { let dmabuf = crate::wayland::dmabuf::get_dmabuf(buffer) .expect("import_dma_buffer without checking buffer type?"); self.import_dmabuf(dmabuf, Some(damage)) @@ -528,7 +532,7 @@ pub trait ImportDma: Renderer { &mut self, dmabuf: &Dmabuf, damage: Option<&[Rectangle<i32, BufferCoord>]>, - ) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>; + ) -> Result<Self::TextureId, Self::Error>; } // TODO: Replace this with a trait_alias, once that is stabilized. @@ -560,7 +564,7 @@ pub trait ImportAll: Renderer { buffer: &wl_buffer::WlBuffer, surface: Option<&crate::wayland::compositor::SurfaceData>, damage: &[Rectangle<i32, BufferCoord>], - ) -> Option<Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>>; + ) -> Option<Result<Self::TextureId, Self::Error>>; } // TODO: Do this with specialization, when possible and do default implementations @@ -576,7 +580,7 @@ impl<R: Renderer + ImportMemWl + ImportEgl + ImportDmaWl> ImportAll for R { buffer: &wl_buffer::WlBuffer, surface: Option<&SurfaceData>, damage: &[Rectangle<i32, BufferCoord>], - ) -> Option<Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>> { + ) -> Option<Result<Self::TextureId, Self::Error>> { match buffer_type(buffer) { Some(BufferType::Shm) => Some(self.import_shm_buffer(buffer, surface, damage)), Some(BufferType::Egl) => Some(self.import_egl_buffer(buffer, surface, damage)), @@ -596,7 +600,7 @@ impl<R: Renderer + ImportMemWl + ImportDmaWl> ImportAll for R { buffer: &wl_buffer::WlBuffer, surface: Option<&SurfaceData>, damage: &[Rectangle<i32, BufferCoord>], - ) -> Option<Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>> { + ) -> Option<Result<Self::TextureId, Self::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, surface, damage)), @@ -610,7 +614,7 @@ pub trait ExportMem: Renderer { /// Texture type representing a downloaded pixel buffer. type TextureMapping: TextureMapping; - /// Copies the contents of the currently bound framebuffer. + /// Copies the contents of the provided target. /// /// This operation is not destructive, the contents of the framebuffer keep being valid. /// @@ -621,9 +625,10 @@ pub trait ExportMem: Renderer { /// - It is not possible to convert the framebuffer into the provided format. fn copy_framebuffer( &mut self, + target: &Self::Framebuffer<'_>, region: Rectangle<i32, BufferCoord>, format: Fourcc, - ) -> Result<Self::TextureMapping, <Self as Renderer>::Error>; + ) -> Result<Self::TextureMapping, Self::Error>; /// Copies the contents of the passed texture. /// *Note*: This function may change or invalidate the current bind. @@ -659,64 +664,36 @@ pub trait ExportMem: Renderer { /// /// This function *may* fail, if (but not limited to): /// - There is not enough space in memory - fn map_texture<'a>( - &mut self, - texture_mapping: &'a Self::TextureMapping, - ) -> Result<&'a [u8], <Self as Renderer>::Error>; + fn map_texture<'a>(&mut self, texture_mapping: &'a Self::TextureMapping) + -> Result<&'a [u8], Self::Error>; } /// Trait for renderers supporting blitting contents from one framebuffer to another. -pub trait Blit<Target> +pub trait Blit where - Self: Renderer + Bind<Target>, + Self: Renderer, { - /// Copies the contents of `src` in the current bound framebuffer to `dst` in Target, - /// applying `filter` if necessary. - /// - /// This operation is non destructive, the contents of the source framebuffer - /// are kept intact as is any region not in `dst` for the target framebuffer. - /// - /// This operation needs a bound or default rendering target. - /// The currently bound target is guaranteed to still be active after this operation. - /// - /// This function *may* fail, if (but not limited to): - /// - The source framebuffer is not readable / unset - /// - The destination framebuffer is not writable - /// - `src` is out of bounds for the source framebuffer - /// - `dst` is out of bounds for the destination framebuffer - /// - `src` and `dst` sizes are different and interpolation id not supported by this renderer. - /// - source and target framebuffer are the same, and `src` and `dst` overlap - fn blit_to( - &mut self, - to: Target, - src: Rectangle<i32, Physical>, - dst: Rectangle<i32, Physical>, - filter: TextureFilter, - ) -> Result<(), <Self as Renderer>::Error>; - - /// Copies the contents of `src` in Target to `dst` of the current bound framebuffer, + /// Copies the contents of `src` from one provided target to `dst` in the other provided target, /// applying `filter` if necessary. /// /// This operation is non destructive, the contents of the source framebuffer /// are kept intact as is any region not in `dst` for the target framebuffer. /// - /// This operation needs a bound or default rendering target. - /// The currently bound target is guaranteed to still be active after this operation. - /// /// This function *may* fail, if (but not limited to): /// - The source framebuffer is not readable - /// - The destination framebuffer is not writable / unset + /// - The destination framebuffer is not writable /// - `src` is out of bounds for the source framebuffer /// - `dst` is out of bounds for the destination framebuffer /// - `src` and `dst` sizes are different and interpolation id not supported by this renderer. /// - source and target framebuffer are the same, and `src` and `dst` overlap - fn blit_from( + fn blit( &mut self, - from: Target, + from: &Self::Framebuffer<'_>, + to: &mut Self::Framebuffer<'_>, src: Rectangle<i32, Physical>, dst: Rectangle<i32, Physical>, filter: TextureFilter, - ) -> Result<(), <Self as Renderer>::Error>; + ) -> Result<(), Self::Error>; } #[cfg(feature = "wayland_frontend")] diff --git a/src/backend/renderer/multigpu/gbm.rs b/src/backend/renderer/multigpu/gbm.rs index e89b2fc1928d..32e75a1c2bca 100644 --- a/src/backend/renderer/multigpu/gbm.rs +++ b/src/backend/renderer/multigpu/gbm.rs @@ -16,7 +16,7 @@ use crate::backend::{ renderer::{ gles::{GlesError, GlesRenderer}, multigpu::{ApiDevice, Error as MultiError, GraphicsApi}, - Renderer, + Renderer, RendererSuper, }, SwapBuffersError, }; @@ -223,7 +223,7 @@ impl<T: GraphicsApi, R: From<GlesRenderer> + Renderer<Error = GlesError>, A: AsF std::convert::From<GlesError> for MultiError<GbmGlesBackend<R, A>, T> where T::Error: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, { #[inline] fn from(err: GlesError) -> MultiError<GbmGlesBackend<R, A>, T> { @@ -278,7 +278,7 @@ where + ImportEgl + ExportMem + 'static, - <R as Renderer>::TextureId: Clone + Send, + R::TextureId: Clone + Send, { fn bind_wl_display(&mut self, display: &wayland_server::DisplayHandle) -> Result<(), EGLError> { self.render.renderer_mut().bind_wl_display(display) @@ -296,7 +296,7 @@ where buffer: &wl_buffer::WlBuffer, surface: Option<&crate::wayland::compositor::SurfaceData>, damage: &[Rectangle<i32, BufferCoords>], - ) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error> { + ) -> Result<Self::TextureId, Self::Error> { if let Some(dmabuf) = Self::try_import_egl(self.render.renderer_mut(), buffer) .ok() .or_else(|| { @@ -360,11 +360,14 @@ where ))); } - renderer - .borrow_mut() - .make_current() - .map_err(GlesError::from) - .map_err(MultigpuError::Render)?; + unsafe { + renderer + .borrow_mut() + .egl_context() + .make_current() + .map_err(GlesError::from) + .map_err(MultigpuError::Render)? + }; let egl = renderer .egl_reader() diff --git a/src/backend/renderer/multigpu/mod.rs b/src/backend/renderer/multigpu/mod.rs index 035ce3b24acc..218d0155f0c0 100644 --- a/src/backend/renderer/multigpu/mod.rs +++ b/src/backend/renderer/multigpu/mod.rs @@ -39,6 +39,7 @@ //! and desired target-gpu are up to be implemented by the compositor. The module only //! reduces the amount of necessary setup operations. //! +use aliasable::boxed::AliasableBox; use std::{ any::{Any, TypeId}, collections::HashMap, @@ -48,7 +49,7 @@ use std::{ use super::{ sync::SyncPoint, Bind, Blit, Color32F, DebugFlags, ExportMem, Frame, ImportDma, ImportMem, Offscreen, - Renderer, Texture, TextureFilter, TextureMapping, Unbind, + Renderer, RendererSuper, Texture, TextureFilter, TextureMapping, }; #[cfg(feature = "wayland_frontend")] use super::{ImportDmaWl, ImportMemWl}; @@ -93,8 +94,8 @@ pub enum Error<R: GraphicsApi, T: GraphicsApi> where R::Error: 'static, T::Error: 'static, - <<R::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, { /// The graphics api errored on device enumeration #[error("The render graphics api failed enumerating devices {0:?}")] @@ -113,10 +114,10 @@ where DeviceMissing, /// Error on the rendering device #[error("Error on the rendering device: {0:}")] - Render(#[source] <<R::Device as ApiDevice>::Renderer as Renderer>::Error), + Render(#[source] <<R::Device as ApiDevice>::Renderer as RendererSuper>::Error), /// Error on the target device #[error("Error on the target device: {0:}")] - Target(#[source] <<T::Device as ApiDevice>::Renderer as Renderer>::Error), + Target(#[source] <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error), /// Failed to import buffer using the api on any device #[error("Failed to import buffer")] ImportFailed, @@ -161,8 +162,8 @@ impl<R: GraphicsApi, T: GraphicsApi> fmt::Debug for Error<R, T> where R::Error: 'static, T::Error: 'static, - <<R::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -183,8 +184,8 @@ impl<R: GraphicsApi + 'static, T: GraphicsApi + 'static> From<Error<R, T>> for S where R::Error: Into<SwapBuffersError> + Send + Sync, T::Error: Into<SwapBuffersError> + Send + Sync, - <<R::Device as ApiDevice>::Renderer as Renderer>::Error: Into<SwapBuffersError> + Send + Sync, - <<T::Device as ApiDevice>::Renderer as Renderer>::Error: Into<SwapBuffersError> + Send + Sync, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Error: Into<SwapBuffersError> + Send + Sync, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error: Into<SwapBuffersError> + Send + Sync, { #[inline] fn from(err: Error<R, T>) -> SwapBuffersError { @@ -585,7 +586,8 @@ impl<A: GraphicsApi> GpuManager<A> { let src_texture = match api_textures.get(&src_node).unwrap() { GpuSingleTexture::Direct(tex) => tex - .downcast_ref::<<<A::Device as ApiDevice>::Renderer as Renderer>::TextureId>() + .downcast_ref::<<<A::Device as ApiDevice>::Renderer as RendererSuper>::TextureId>( + ) .unwrap(), _ => unreachable!(), }; @@ -753,6 +755,26 @@ impl<R: GraphicsApi, T: GraphicsApi> AsMut<<R::Device as ApiDevice>::Renderer> } } +/// A Framebuffer of a [`MultiRenderer`]. +pub struct MultiFramebuffer<'buffer, R: GraphicsApi, T: GraphicsApi>(MultiFramebufferInternal<'buffer, R, T>); +enum MultiFramebufferInternal<'buffer, R: GraphicsApi, T: GraphicsApi> { + Render(<<R::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'buffer>), + Target(<<T::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'buffer>), +} + +impl<'buffer, R: GraphicsApi, T: GraphicsApi> fmt::Debug for MultiFramebuffer<'buffer, R, T> +where + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'buffer>: fmt::Debug, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'buffer>: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match &self.0 { + MultiFramebufferInternal::Render(framebuffer) => framebuffer.fmt(f), + MultiFramebufferInternal::Target(framebuffer) => framebuffer.fmt(f), + } + } +} + /// [`Frame`] implementation of a [`MultiRenderer`]. /// /// Leaking the frame will potentially keep it from doing necessary copies @@ -760,21 +782,23 @@ impl<R: GraphicsApi, T: GraphicsApi> AsMut<<R::Device as ApiDevice>::Renderer> /// be no updated framebuffer contents. /// Additionally all problems related to the Frame-implementation of the underlying /// [`GraphicsApi`] will be present. -pub struct MultiFrame<'render, 'target, 'frame, R: GraphicsApi + 'frame, T: GraphicsApi> +pub struct MultiFrame<'render, 'target, 'frame, 'buffer, R: GraphicsApi, T: GraphicsApi> where + 'buffer: 'frame, R: 'static, R::Error: 'static, T::Error: 'static, <R::Device as ApiDevice>::Renderer: ExportMem + ImportDma + ImportMem, <T::Device as ApiDevice>::Renderer: ImportDma + ImportMem, - <<R::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, { node: DrmNode, - frame: Option<<<R::Device as ApiDevice>::Renderer as Renderer>::Frame<'frame>>, + frame: Option<<<R::Device as ApiDevice>::Renderer as RendererSuper>::Frame<'frame, 'buffer>>, + framebuffer: + Option<AliasableBox<<<R::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'frame>>>, + target: Option<TargetFrameData<'target, 'frame, 'buffer, T>>, render: *mut &'render mut R::Device, - target: &'frame mut Option<TargetData<'target, T>>, - target_texture: Option<<<T::Device as ApiDevice>::Renderer as Renderer>::TextureId>, dst_transform: Transform, size: Size<i32, Physical>, @@ -788,16 +812,25 @@ struct TargetData<'target, T: GraphicsApi> { format: Fourcc, } -impl<'frame, R: GraphicsApi + 'frame, T: GraphicsApi> fmt::Debug for MultiFrame<'_, '_, 'frame, R, T> +struct TargetFrameData<'target, 'frame, 'buffer, T: GraphicsApi> { + device: &'frame mut &'target mut T::Device, + framebuffer: &'frame mut <<T::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'buffer>, + texture: Option<<<T::Device as ApiDevice>::Renderer as RendererSuper>::TextureId>, + format: Fourcc, +} + +impl<'frame, 'buffer, R: GraphicsApi + 'frame, T: GraphicsApi> fmt::Debug + for MultiFrame<'_, '_, 'frame, 'buffer, R, T> where + 'buffer: 'frame, R: 'static, R::Error: 'static, T::Error: 'static, <R::Device as ApiDevice>::Renderer: ExportMem + ImportDma + ImportMem, <T::Device as ApiDevice>::Renderer: ImportDma + ImportMem, - <<R::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::TextureId: fmt::Debug, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: fmt::Debug, R::Device: fmt::Debug, T::Device: fmt::Debug, { @@ -816,7 +849,7 @@ where impl<T: GraphicsApi> fmt::Debug for TargetData<'_, T> where T::Device: fmt::Debug, - <<T::Device as ApiDevice>::Renderer as Renderer>::TextureId: fmt::Debug, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("TargetData") @@ -827,68 +860,60 @@ where } } +impl<T: GraphicsApi> fmt::Debug for TargetFrameData<'_, '_, '_, T> +where + T::Device: fmt::Debug, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TargetFrameData") + .field("device", self.device) + .field("format", &self.format) + .finish_non_exhaustive() + } +} + // These casts are ok, because the frame cannot outlive the MultiFrame, // see MultiRenderer::render for how this hack works and why it is necessary. -impl<'frame, R: GraphicsApi, T: GraphicsApi> - AsRef<<<R::Device as ApiDevice>::Renderer as Renderer>::Frame<'frame>> - for MultiFrame<'_, '_, 'frame, R, T> +impl<'frame, 'buffer, R: GraphicsApi, T: GraphicsApi> + AsRef<<<R::Device as ApiDevice>::Renderer as RendererSuper>::Frame<'frame, 'buffer>> + for MultiFrame<'_, '_, 'frame, 'buffer, R, T> where + 'buffer: 'frame, R: 'static, R::Error: 'static, T::Error: 'static, <R::Device as ApiDevice>::Renderer: ExportMem + ImportDma + ImportMem, <T::Device as ApiDevice>::Renderer: ImportDma + ImportMem, - <<R::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, { - fn as_ref(&self) -> &<<R::Device as ApiDevice>::Renderer as Renderer>::Frame<'frame> { + fn as_ref(&self) -> &<<R::Device as ApiDevice>::Renderer as RendererSuper>::Frame<'frame, 'buffer> { self.frame.as_ref().unwrap() } } -impl<'frame, R: GraphicsApi, T: GraphicsApi> - AsMut<<<R::Device as ApiDevice>::Renderer as Renderer>::Frame<'frame>> - for MultiFrame<'_, '_, 'frame, R, T> +impl<'frame, 'buffer, R: GraphicsApi, T: GraphicsApi> + AsMut<<<R::Device as ApiDevice>::Renderer as RendererSuper>::Frame<'frame, 'buffer>> + for MultiFrame<'_, '_, 'frame, 'buffer, R, T> where + 'buffer: 'frame, R: 'static, R::Error: 'static, T::Error: 'static, <R::Device as ApiDevice>::Renderer: ExportMem + ImportDma + ImportMem, <T::Device as ApiDevice>::Renderer: ImportDma + ImportMem, - <<R::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, { - fn as_mut(&mut self) -> &mut <<R::Device as ApiDevice>::Renderer as Renderer>::Frame<'frame> { + fn as_mut( + &mut self, + ) -> &mut <<R::Device as ApiDevice>::Renderer as RendererSuper>::Frame<'frame, 'buffer> { self.frame.as_mut().unwrap() } } -impl<R: GraphicsApi, T: GraphicsApi> Unbind for MultiRenderer<'_, '_, R, T> -where - <T::Device as ApiDevice>::Renderer: Unbind, - <R::Device as ApiDevice>::Renderer: Unbind, - // We need this because the Renderer-impl does and Unbind requires Renderer - R: 'static, - R::Error: 'static, - T::Error: 'static, - <R::Device as ApiDevice>::Renderer: Bind<Dmabuf> + ExportMem + ImportDma + ImportMem, - <T::Device as ApiDevice>::Renderer: ImportDma + ImportMem, - <<R::Device as ApiDevice>::Renderer as Renderer>::TextureId: Clone + Send, - <<R::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, -{ - #[instrument(level = "trace", parent = &self.span, skip(self))] - #[profiling::function] - fn unbind(&mut self) -> Result<(), <Self as Renderer>::Error> { - if let Some(target) = self.target.as_mut() { - target.device.renderer_mut().unbind().map_err(Error::Target) - } else { - self.render.renderer_mut().unbind().map_err(Error::Render) - } - } -} - impl<R: GraphicsApi, T: GraphicsApi, Target> Offscreen<Target> for MultiRenderer<'_, '_, R, T> where <T::Device as ApiDevice>::Renderer: Offscreen<Target>, @@ -896,18 +921,15 @@ where // We need these because the Bind-impl does and Offscreen requires Bind <T::Device as ApiDevice>::Renderer: Bind<Target>, <R::Device as ApiDevice>::Renderer: Bind<Target>, - // We need these because the Unbind-impl does and Offscreen requires Bind, which requires Unbind - <R::Device as ApiDevice>::Renderer: Unbind, - <T::Device as ApiDevice>::Renderer: Unbind, // We need these because the Renderer-impl does and Offscreen requires Bind, which requires Unbind, which requires Renderer R: 'static, R::Error: 'static, T::Error: 'static, <R::Device as ApiDevice>::Renderer: Bind<Dmabuf> + ExportMem + ImportDma + ImportMem, <T::Device as ApiDevice>::Renderer: ImportDma + ImportMem, - <<R::Device as ApiDevice>::Renderer as Renderer>::TextureId: Clone + Send, - <<R::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: Clone + Send, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, { #[instrument(level = "trace", parent = &self.span, skip(self))] #[profiling::function] @@ -915,7 +937,7 @@ where &mut self, format: Fourcc, size: Size<i32, BufferCoords>, - ) -> Result<Target, <Self as Renderer>::Error> { + ) -> Result<Target, <Self as RendererSuper>::Error> { if let Some(target) = self.target.as_mut() { target .device @@ -935,26 +957,37 @@ impl<R: GraphicsApi, T: GraphicsApi, Target> Bind<Target> for MultiRenderer<'_, where <T::Device as ApiDevice>::Renderer: Bind<Target>, <R::Device as ApiDevice>::Renderer: Bind<Target>, - // We need these because the Unbind-impl does and Bind requires Unbind - <R::Device as ApiDevice>::Renderer: Unbind, - <T::Device as ApiDevice>::Renderer: Unbind, // We need this because the Renderer-impl does and Bind requires Unbind, which requires Renderer R: 'static, R::Error: 'static, T::Error: 'static, <R::Device as ApiDevice>::Renderer: Bind<Dmabuf> + ExportMem + ImportDma + ImportMem, <T::Device as ApiDevice>::Renderer: ImportDma + ImportMem, - <<R::Device as ApiDevice>::Renderer as Renderer>::TextureId: Clone + Send, - <<R::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: Clone + Send, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, { #[instrument(level = "trace", parent = &self.span, skip(self, bind))] #[profiling::function] - fn bind(&mut self, bind: Target) -> Result<(), <Self as Renderer>::Error> { + fn bind<'a>( + &mut self, + bind: &'a mut Target, + ) -> Result<<Self as RendererSuper>::Framebuffer<'a>, <Self as RendererSuper>::Error> { if let Some(target) = self.target.as_mut() { - target.device.renderer_mut().bind(bind).map_err(Error::Target) + target + .device + .renderer_mut() + .bind(bind) + .map(MultiFramebufferInternal::Target) + .map(MultiFramebuffer) + .map_err(Error::Target) } else { - self.render.renderer_mut().bind(bind).map_err(Error::Render) + self.render + .renderer_mut() + .bind(bind) + .map(MultiFramebufferInternal::Render) + .map(MultiFramebuffer) + .map_err(Error::Render) } } @@ -969,24 +1002,38 @@ where static MAX_CPU_COPIES: usize = 3; // TODO, benchmark this -impl<'render, 'target, R: GraphicsApi, T: GraphicsApi> Renderer for MultiRenderer<'render, 'target, R, T> +impl<'render, 'target, R: GraphicsApi, T: GraphicsApi> RendererSuper for MultiRenderer<'render, 'target, R, T> where R: 'static, R::Error: 'static, T::Error: 'static, <R::Device as ApiDevice>::Renderer: Bind<Dmabuf> + ExportMem + ImportDma + ImportMem, <T::Device as ApiDevice>::Renderer: ImportDma + ImportMem, - <<R::Device as ApiDevice>::Renderer as Renderer>::TextureId: Clone + Send, - <<R::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: Clone + Send, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, { type Error = Error<R, T>; type TextureId = MultiTexture; - type Frame<'frame> - = MultiFrame<'render, 'target, 'frame, R, T> + type Framebuffer<'buffer> = MultiFramebuffer<'buffer, R, T>; + type Frame<'frame, 'buffer> + = MultiFrame<'render, 'target, 'frame, 'buffer, R, T> where + 'buffer: 'frame, Self: 'frame; +} +impl<'render, 'target, R: GraphicsApi, T: GraphicsApi> Renderer for MultiRenderer<'render, 'target, R, T> +where + R: 'static, + R::Error: 'static, + T::Error: 'static, + <R::Device as ApiDevice>::Renderer: Bind<Dmabuf> + ExportMem + ImportDma + ImportMem, + <T::Device as ApiDevice>::Renderer: ImportDma + ImportMem, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: Clone + Send, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, +{ fn id(&self) -> usize { self.render.renderer().id() } @@ -1011,14 +1058,18 @@ where self.render.renderer().debug_flags() } - #[instrument(level = "trace", parent = &self.span, skip(self))] + #[instrument(level = "trace", parent = &self.span, skip(self, framebuffer))] #[profiling::function] - fn render<'frame>( + fn render<'frame, 'buffer>( &'frame mut self, + framebuffer: &'frame mut Self::Framebuffer<'buffer>, size: Size<i32, Physical>, dst_transform: Transform, - ) -> Result<MultiFrame<'render, 'target, 'frame, R, T>, Self::Error> { - let target_texture = if let Some(target) = self.target.as_mut() { + ) -> Result<MultiFrame<'render, 'target, 'frame, 'buffer, R, T>, Self::Error> + where + 'buffer: 'frame, + { + let target_state = if let Some(target) = self.target.as_mut() { let buffer_size = size.to_logical(1).to_buffer(1, Transform::Normal); if let Some((_, dmabuf)) = &target.cached_buffer { @@ -1046,7 +1097,7 @@ where .filter(|format| format.code == target.format) .map(|f| f.modifier) .collect::<Vec<_>>(); - let dmabuf = self + let mut dmabuf = self .render .allocator() .create_buffer( @@ -1057,18 +1108,29 @@ where ) .map_err(Error::AllocatorError)?; + { + // make sure we mark this as a framebuffer on render first (some GL drivers don't like us to do this later). + let mut render_framebuffer = self + .render + .renderer_mut() + .bind(&mut dmabuf) + .map_err(Error::Render)?; + self.render + .renderer_mut() + .render(&mut render_framebuffer, size, dst_transform) + .map_err(Error::Render)?; + // drop everything + } + *target.cached_buffer = Some((false, dmabuf)); } } }; // try to import on target node - let (direct, dmabuf) = target.cached_buffer.as_mut().unwrap(); - self.render - .renderer_mut() - .bind(dmabuf.clone()) - .map_err(Error::Render)?; - (*direct) + let (direct, ref mut dmabuf) = target.cached_buffer.as_mut().unwrap(); + // TODO: We could cache that texture all the way back to the GpuManager in a HashMap<WeakDmabuf, Texture>. + let texture = (*direct) .then(|| { target .device @@ -1076,35 +1138,70 @@ where .import_dmabuf(dmabuf, Some(&[Rectangle::from_size(buffer_size)])) .map_err(Error::Target) }) - .transpose()? + .transpose()?; + let framebuffer = self.render.renderer_mut().bind(dmabuf).map_err(Error::Render)?; - // TODO: We could cache that texture all the way back to the GpuManager in a HashMap<WeakDmabuf, Texture>. + Some((&mut target.device, framebuffer, texture, target.format)) } else { None }; let node = *self.render.node(); - let ptr = &mut self.render as *mut _; - let frame = self - .render - .renderer_mut() - .render(size, dst_transform) - .map_err(Error::Render)?; + + let mut target = None; + let mut new_framebuffer = None; + let frame = match &mut framebuffer.0 { + MultiFramebufferInternal::Render(framebuffer) => self + .render + .renderer_mut() + .render(framebuffer, size, dst_transform) + .map_err(Error::Render)?, + MultiFramebufferInternal::Target(target_framebuffer) => { + let (target_device, render_framebuffer, texture, format) = target_state.unwrap(); + target = Some(TargetFrameData { + device: target_device, + framebuffer: target_framebuffer, + texture, + format, + }); + let mut render_framebuffer = AliasableBox::from_unique(Box::new(render_framebuffer)); + + // We extend the lifetime to 'frame, because this is self-referencial. + // SAFETY: + // - We drop the framebuffer before `target`, which contains the referenced dmabuf + // - We drop the frame before the framebuffer as we store both in `MultiFrame` + // - `Frame` can't store an invalid pointer into the framebuffer, as the framebuffer is moved + // to the heap and won't be moved by the compiler thanks to `AliasableBox`. + let frame = unsafe { + std::mem::transmute::< + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Frame<'_, '_>, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Frame<'frame, 'buffer>, + >( + self.render + .renderer_mut() + .render(&mut *render_framebuffer, size, dst_transform) + .map_err(Error::Render)?, + ) + }; + new_framebuffer = Some(render_framebuffer); + frame + } + }; let span = trace_span!( parent: &self.span, "renderer_multi_frame", - direct = target_texture.is_some(), + direct = target.as_ref().is_some_and(|t| t.texture.is_some()), ) .entered(); Ok(MultiFrame { node, frame: Some(frame), + framebuffer: new_framebuffer, render: ptr, // this is fine, as long as we have the frame, this ptr is valid - target: &mut self.target, - target_texture, + target, dst_transform, size, damage: Vec::new(), @@ -1145,8 +1242,8 @@ where T::Error: 'static, <R::Device as ApiDevice>::Renderer: Bind<Dmabuf> + ExportMem + ImportDma + ImportMem, <T::Device as ApiDevice>::Renderer: ImportDma + ImportMem, - <<R::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, { let target_formats = ImportDma::dmabuf_formats(target.device.renderer()) .iter() @@ -1172,7 +1269,7 @@ where target_modifiers, ); - let dmabuf = src + let mut dmabuf = src .allocator() .create_buffer( buffer_size.w as u32, @@ -1184,7 +1281,7 @@ where // verify we can bind on src and import on target - src.renderer_mut().bind(dmabuf.clone()).map_err(Error::Render)?; + src.renderer_mut().bind(&mut dmabuf).map_err(Error::Render)?; target .device @@ -1195,15 +1292,15 @@ where Ok(dmabuf) } -impl<R: GraphicsApi, T: GraphicsApi> MultiFrame<'_, '_, '_, R, T> +impl<R: GraphicsApi, T: GraphicsApi> MultiFrame<'_, '_, '_, '_, R, T> where R: 'static, R::Error: 'static, T::Error: 'static, <R::Device as ApiDevice>::Renderer: ExportMem + ImportDma + ImportMem, <T::Device as ApiDevice>::Renderer: ImportDma + ImportMem, - <<R::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, { #[instrument(level = "trace", parent = &self.span, skip(self))] #[profiling::function] @@ -1228,7 +1325,7 @@ where let buffer_size = self.size.to_logical(1).to_buffer(1, Transform::Normal); if let Some(target) = self.target.as_mut() { - if let Some(texture) = self.target_texture.as_ref() { + if let Some(texture) = target.texture.take() { // try gpu copy let damage = damage .iter() @@ -1237,7 +1334,7 @@ where let mut frame = target .device .renderer_mut() - .render(self.size, Transform::Normal) + .render(target.framebuffer, self.size, Transform::Normal) .map_err(Error::Target)?; frame.wait(&sync).map_err(Error::Target)?; frame @@ -1245,7 +1342,7 @@ where .map_err(Error::Target)?; frame .render_texture_from_to( - texture, + &texture, Rectangle::from_size(buffer_size).to_f64(), Rectangle::from_size(self.size), &damage, @@ -1300,8 +1397,13 @@ where let mut mappings = Vec::new(); for rect in copy_rects { let mapping = ( - ExportMem::copy_framebuffer(render.renderer_mut(), rect, format) - .map_err(Error::Render)?, + ExportMem::copy_framebuffer( + render.renderer_mut(), + self.framebuffer.as_ref().unwrap(), + rect, + format, + ) + .map_err(Error::Render)?, rect, ); mappings.push(mapping); @@ -1332,7 +1434,7 @@ where let mut frame = target .device .renderer_mut() - .render(self.size, Transform::Normal) + .render(target.framebuffer, self.size, Transform::Normal) .map_err(Error::Target)?; for (texture, rect) in textures { for damage_rect in damage.iter().filter_map(|dmg_rect| dmg_rect.intersection(rect)) { @@ -1376,15 +1478,15 @@ where } } -impl<R: GraphicsApi, T: GraphicsApi> Drop for MultiFrame<'_, '_, '_, R, T> +impl<R: GraphicsApi, T: GraphicsApi> Drop for MultiFrame<'_, '_, '_, '_, R, T> where R: 'static, R::Error: 'static, T::Error: 'static, <R::Device as ApiDevice>::Renderer: ExportMem + ImportDma + ImportMem, <T::Device as ApiDevice>::Renderer: ImportDma + ImportMem, - <<R::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, { fn drop(&mut self) { if let Err(err) = self.finish_internal() { @@ -1478,9 +1580,9 @@ impl MultiTexture { pub fn get<A: GraphicsApi + 'static>( &self, render: &DrmNode, - ) -> Option<<<A::Device as ApiDevice>::Renderer as Renderer>::TextureId> + ) -> Option<<<A::Device as ApiDevice>::Renderer as RendererSuper>::TextureId> where - <<A::Device as ApiDevice>::Renderer as Renderer>::TextureId: Clone + Send + 'static, + <<A::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: Clone + Send + 'static, { let tex = self.0.lock().unwrap(); tex.textures @@ -1492,7 +1594,7 @@ impl MultiTexture { GpuSingleTexture::Mem { texture, .. } => texture.as_ref(), }) .and_then(|texture| { - <dyn Any>::downcast_ref::<<<A::Device as ApiDevice>::Renderer as Renderer>::TextureId>( + <dyn Any>::downcast_ref::<<<A::Device as ApiDevice>::Renderer as RendererSuper>::TextureId>( &**texture, ) }) @@ -1501,7 +1603,7 @@ impl MultiTexture { fn needs_synchronization<A: GraphicsApi + 'static>(&self, render: &DrmNode) -> Option<SyncPoint> where - <<A::Device as ApiDevice>::Renderer as Renderer>::TextureId: 'static, + <<A::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: 'static, { let mut tex = self.0.lock().unwrap(); tex.textures @@ -1517,9 +1619,9 @@ impl MultiTexture { fn insert_texture<A: GraphicsApi + 'static>( &mut self, render: DrmNode, - texture: <<A::Device as ApiDevice>::Renderer as Renderer>::TextureId, + texture: <<A::Device as ApiDevice>::Renderer as RendererSuper>::TextureId, ) where - <<A::Device as ApiDevice>::Renderer as Renderer>::TextureId: 'static, + <<A::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: 'static, { let mut tex = self.0.lock().unwrap(); let format = texture.format(); @@ -1575,7 +1677,7 @@ impl MultiTexture { }) .unwrap_or((None, None, None)); let old_texture = old_texture.filter(|tex| { - <dyn Any>::downcast_ref::<<<R::Device as ApiDevice>::Renderer as Renderer>::TextureId>(tex) + <dyn Any>::downcast_ref::<<<R::Device as ApiDevice>::Renderer as RendererSuper>::TextureId>(tex) .map(|tex| tex.size()) == Some(size) }); @@ -1598,7 +1700,7 @@ impl MultiTexture { true } }) - .map(|(r, m)| (r, Box::new(m) as Box<_>)) + .map(|(r, m)| (r, Box::new(m) as Box<dyn Any + 'static>)) .collect::<Vec<_>>(); mappings.retain(|(region, _)| { !new_mappings @@ -1633,16 +1735,16 @@ impl Texture for MultiTexture { } } -impl<R: GraphicsApi, T: GraphicsApi> Frame for MultiFrame<'_, '_, '_, R, T> +impl<R: GraphicsApi, T: GraphicsApi> Frame for MultiFrame<'_, '_, '_, '_, R, T> where R: 'static, R::Error: 'static, T::Error: 'static, <R::Device as ApiDevice>::Renderer: ExportMem + ImportDma + ImportMem, <T::Device as ApiDevice>::Renderer: ImportDma + ImportMem, - <<R::Device as ApiDevice>::Renderer as Renderer>::TextureId: Clone + Send, - <<R::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: Clone + Send, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, { type TextureId = MultiTexture; type Error = Error<R, T>; @@ -1746,9 +1848,9 @@ where T::Error: 'static, <R::Device as ApiDevice>::Renderer: Bind<Dmabuf> + ExportMem + ImportDma + ImportMem, <T::Device as ApiDevice>::Renderer: ImportDma + ImportMem, - <<R::Device as ApiDevice>::Renderer as Renderer>::TextureId: Clone + Send, - <<R::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: Clone + Send, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, { #[instrument(level = "trace", parent = &self.span, skip(self))] #[profiling::function] @@ -1757,7 +1859,7 @@ where buffer: &wl_buffer::WlBuffer, surface: Option<&crate::wayland::compositor::SurfaceData>, damage: &[Rectangle<i32, BufferCoords>], - ) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error> { + ) -> Result<<Self as RendererSuper>::TextureId, <Self as RendererSuper>::Error> { let shm_texture = self .render .renderer_mut() @@ -1794,9 +1896,9 @@ where T::Error: 'static, <R::Device as ApiDevice>::Renderer: Bind<Dmabuf> + ExportMem + ImportDma + ImportMem, <T::Device as ApiDevice>::Renderer: ImportDma + ImportMem, - <<R::Device as ApiDevice>::Renderer as Renderer>::TextureId: Clone + Send, - <<R::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: Clone + Send, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, { #[instrument(level = "trace", parent = &self.span, skip(self))] #[profiling::function] @@ -1806,7 +1908,7 @@ where format: Fourcc, size: Size<i32, BufferCoords>, flipped: bool, - ) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error> { + ) -> Result<<Self as RendererSuper>::TextureId, <Self as RendererSuper>::Error> { let mem_texture = self .render .renderer_mut() @@ -1827,10 +1929,10 @@ where #[profiling::function] fn update_memory( &mut self, - texture: &<Self as Renderer>::TextureId, + texture: &<Self as RendererSuper>::TextureId, data: &[u8], region: Rectangle<i32, BufferCoords>, - ) -> Result<(), <Self as Renderer>::Error> { + ) -> Result<(), <Self as RendererSuper>::Error> { let mem_texture = texture .get::<R>(self.render.node()) .ok_or_else(|| Error::MismatchedDevice(*self.render.node()))?; @@ -1857,9 +1959,9 @@ where R: 'static, <R::Device as ApiDevice>::Renderer: Bind<Dmabuf> + ExportMem + ImportDma + ImportMem, <T::Device as ApiDevice>::Renderer: Bind<Dmabuf> + ImportDma + ImportMem, - <<R::Device as ApiDevice>::Renderer as Renderer>::TextureId: Clone + Send, - <<R::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: Clone + Send, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, { #[instrument(level = "trace", parent = &self.span, skip(self))] #[profiling::function] @@ -1868,7 +1970,7 @@ where buffer: &wl_buffer::WlBuffer, surface: Option<&SurfaceData>, damage: &[Rectangle<i32, BufferCoords>], - ) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error> { + ) -> Result<<Self as RendererSuper>::TextureId, <Self as RendererSuper>::Error> { let dmabuf = get_dmabuf(buffer).expect("import_dma_buffer without checking buffer type?"); let texture = MultiTexture::from_surface(surface, dmabuf.size(), dmabuf.format()); let texture_ref = texture.0.clone(); @@ -1893,9 +1995,9 @@ where R: 'static, <R::Device as ApiDevice>::Renderer: Bind<Dmabuf> + ExportMem + ImportDma + ImportMem, <T::Device as ApiDevice>::Renderer: ImportDma + ImportMem, - <<R::Device as ApiDevice>::Renderer as Renderer>::TextureId: Clone + Send, - <<R::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: Clone + Send, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, { fn dmabuf_formats(&self) -> FormatSet { ImportDma::dmabuf_formats(self.render.renderer()) @@ -1911,7 +2013,7 @@ where &mut self, dmabuf: &Dmabuf, damage: Option<&[Rectangle<i32, BufferCoords>]>, - ) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error> { + ) -> Result<<Self as RendererSuper>::TextureId, <Self as RendererSuper>::Error> { let texture = MultiTexture::new(dmabuf.size(), dmabuf.format()); self.import_dmabuf_internal(dmabuf, texture, damage) } @@ -1929,10 +2031,10 @@ where R: GraphicsApi + 'static, <R as GraphicsApi>::Device: 'a, <<R as GraphicsApi>::Device as ApiDevice>::Renderer: Renderer + ImportDma, - <<<R as GraphicsApi>::Device as ApiDevice>::Renderer as Renderer>::TextureId: 'static, + <<<R as GraphicsApi>::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: 'static, T: GraphicsApi + 'static, <<T as GraphicsApi>::Device as ApiDevice>::Renderer: Renderer + ImportDma, - <<<T as GraphicsApi>::Device as ApiDevice>::Renderer as Renderer>::TextureId: 'static, + <<<T as GraphicsApi>::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: 'static, { match dmabuf.node() { Some(node) => { @@ -1994,7 +2096,7 @@ where } fn dma_shadow_copy<S, T>( - src_texture: &<<S::Device as ApiDevice>::Renderer as Renderer>::TextureId, + src_texture: &<<S::Device as ApiDevice>::Renderer as RendererSuper>::TextureId, damage: Option<&[Rectangle<i32, BufferCoords>]>, slot: &mut Option<(Dmabuf, Box<dyn Any + 'static>, Option<SyncPoint>)>, src: &mut S::Device, @@ -2005,8 +2107,8 @@ where T: GraphicsApi, <S::Device as ApiDevice>::Renderer: Renderer + ImportDma + Bind<Dmabuf>, <T::Device as ApiDevice>::Renderer: Renderer + ImportDma, - <<S::Device as ApiDevice>::Renderer as Renderer>::TextureId: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::TextureId: 'static, + <<S::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: 'static, { let format = src_texture.format().unwrap_or(Fourcc::Abgr8888); let read_formats = if let Some(target) = target.as_ref() { @@ -2040,14 +2142,14 @@ where .map_err(Error::AllocatorError)?; let target_texture = if let Some(target) = target.as_mut() { - Box::<<<T::Device as ApiDevice>::Renderer as Renderer>::TextureId>::new( + Box::<<<T::Device as ApiDevice>::Renderer as RendererSuper>::TextureId>::new( target .renderer_mut() .import_dmabuf(&shadow_buffer, None) .map_err(Error::Target)?, ) as Box<dyn Any + 'static> } else { - Box::<<<S::Device as ApiDevice>::Renderer as Renderer>::TextureId>::new( + Box::<<<S::Device as ApiDevice>::Renderer as RendererSuper>::TextureId>::new( src.renderer_mut() .import_dmabuf(&shadow_buffer, None) .map_err(Error::Render)?, @@ -2063,10 +2165,10 @@ where let _ = sync.wait(); // ignore interrupt errors } } - src_renderer.bind(shadow_buffer.clone()).map_err(Error::Render)?; + let mut framebuffer = src_renderer.bind(shadow_buffer).map_err(Error::Render)?; let shadow_size = Size::from((src_texture.width() as i32, src_texture.height() as i32)); let mut frame = src_renderer - .render(shadow_size, Transform::Normal) + .render(&mut framebuffer, shadow_size, Transform::Normal) .map_err(Error::Render)?; let damage_slice = [Rectangle::from_size(shadow_size)]; @@ -2105,11 +2207,11 @@ type BoxedTextureMappingAndDamage<S> = ( type MemTexture<S, T> = ( Option<Vec<BoxedTextureMappingAndDamage<S>>>, - Option<Box<<<<T as GraphicsApi>::Device as ApiDevice>::Renderer as Renderer>::TextureId>>, + Option<Box<<<<T as GraphicsApi>::Device as ApiDevice>::Renderer as RendererSuper>::TextureId>>, ); fn mem_copy<S, T>( - src_texture: &<<S::Device as ApiDevice>::Renderer as Renderer>::TextureId, + src_texture: &<<S::Device as ApiDevice>::Renderer as RendererSuper>::TextureId, damage: Option<&[Rectangle<i32, BufferCoords>]>, slot: &mut Option<MemTexture<S, T>>, src: &mut S::Device, @@ -2244,7 +2346,7 @@ where fn texture_copy<S, T>( src: &mut S::Device, target: &mut T::Device, - src_texture: &<<S::Device as ApiDevice>::Renderer as Renderer>::TextureId, + src_texture: &<<S::Device as ApiDevice>::Renderer as RendererSuper>::TextureId, target_texture: &mut Option<GpuSingleTexture>, damage: Option<&[Rectangle<i32, BufferCoords>]>, ) -> Result<(), Error<S, T>> @@ -2254,8 +2356,8 @@ where <S::Device as ApiDevice>::Renderer: Renderer + ImportDma + ExportMem + Bind<Dmabuf>, <<S::Device as ApiDevice>::Renderer as ExportMem>::TextureMapping: 'static, <T::Device as ApiDevice>::Renderer: Renderer + ImportDma + ImportMem, - <<S::Device as ApiDevice>::Renderer as Renderer>::TextureId: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::TextureId: 'static, + <<S::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: 'static, { // we need to reset in a few cases if matches!(&target_texture, Some(GpuSingleTexture::Direct(_))) @@ -2293,14 +2395,14 @@ where mappings.map(|(_, mappings)| mappings.into_iter().map(|(damage, mapping)| (mapping.downcast::<<<S::Device as ApiDevice>::Renderer as ExportMem>::TextureMapping>().unwrap(), damage) ).collect::<Vec<_>>()), - texture.map(|texture| texture.downcast::<<<T::Device as ApiDevice>::Renderer as Renderer>::TextureId>().unwrap()) + texture.map(|texture| texture.downcast::<<<T::Device as ApiDevice>::Renderer as RendererSuper>::TextureId>().unwrap()) )); let src_texture = external_shadow .as_ref() .map(|(_, texture)| { texture - .downcast_ref::<<<S::Device as ApiDevice>::Renderer as Renderer>::TextureId>() + .downcast_ref::<<<S::Device as ApiDevice>::Renderer as RendererSuper>::TextureId>() .unwrap() }) .unwrap_or(src_texture); @@ -2370,7 +2472,7 @@ where .as_ref() .map(|(_, texture)| { texture - .downcast_ref::<<<S::Device as ApiDevice>::Renderer as Renderer>::TextureId>() + .downcast_ref::<<<S::Device as ApiDevice>::Renderer as RendererSuper>::TextureId>() .unwrap() }) .unwrap_or(src_texture); @@ -2407,9 +2509,9 @@ where R: 'static, <R::Device as ApiDevice>::Renderer: Bind<Dmabuf> + ExportMem + ImportDma + ImportMem, <T::Device as ApiDevice>::Renderer: ImportDma + ImportMem, - <<R::Device as ApiDevice>::Renderer as Renderer>::TextureId: Clone + Send, - <<R::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: Clone + Send, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, { #[profiling::function] fn import_dmabuf_internal( @@ -2417,7 +2519,7 @@ where dmabuf: &Dmabuf, mut texture: MultiTexture, damage: Option<&[Rectangle<i32, BufferCoords>]>, - ) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error> { + ) -> Result<<Self as RendererSuper>::TextureId, <Self as RendererSuper>::Error> { let src_node = import_on_src_node::<R, T>( dmabuf, damage, @@ -2456,7 +2558,7 @@ where }; let src_texture = match src_api_textures[0].1.get(&src_node).unwrap() { GpuSingleTexture::Direct(tex) => tex - .downcast_ref::<<<T::Device as ApiDevice>::Renderer as Renderer>::TextureId>() + .downcast_ref::<<<T::Device as ApiDevice>::Renderer as RendererSuper>::TextureId>() .unwrap(), _ => unreachable!(), }; @@ -2493,7 +2595,7 @@ where let mut target_texture = api_textures.remove(self.render.node()); let src_texture = match api_textures.get(&src_node).unwrap() { GpuSingleTexture::Direct(tex) => tex - .downcast_ref::<<<R::Device as ApiDevice>::Renderer as Renderer>::TextureId>() + .downcast_ref::<<<R::Device as ApiDevice>::Renderer as RendererSuper>::TextureId>() .unwrap(), _ => unreachable!(), }; @@ -2604,32 +2706,36 @@ where T::Error: 'static, <R::Device as ApiDevice>::Renderer: Bind<Dmabuf> + ExportMem + ImportDma + ImportMem, <T::Device as ApiDevice>::Renderer: ImportDma + ImportMem, - <<R::Device as ApiDevice>::Renderer as Renderer>::TextureId: Clone + Send, - <<R::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: Clone + Send, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, { type TextureMapping = MultiTextureMapping<T, R>; - #[instrument(level = "trace", parent = &self.span, skip(self))] + #[instrument(level = "trace", parent = &self.span, skip(self, framebuffer))] #[profiling::function] fn copy_framebuffer( &mut self, + framebuffer: &MultiFramebuffer<'_, R, T>, region: Rectangle<i32, BufferCoords>, format: Fourcc, - ) -> Result<Self::TextureMapping, <Self as Renderer>::Error> { - if let Some(target) = self.target.as_mut() { - target - .device - .renderer_mut() - .copy_framebuffer(region, format) - .map(|mapping| MultiTextureMapping(TextureMappingInternal::Either(mapping))) - .map_err(Error::Target) - } else { - self.render + ) -> Result<Self::TextureMapping, <Self as RendererSuper>::Error> { + match &framebuffer.0 { + MultiFramebufferInternal::Target(fb) => { + let target = self.target.as_mut().unwrap(); + target + .device + .renderer_mut() + .copy_framebuffer(fb, region, format) + .map(|mapping| MultiTextureMapping(TextureMappingInternal::Either(mapping))) + .map_err(Error::Target) + } + MultiFramebufferInternal::Render(fb) => self + .render .renderer_mut() - .copy_framebuffer(region, format) + .copy_framebuffer(fb, region, format) .map(|mapping| MultiTextureMapping(TextureMappingInternal::Or(mapping))) - .map_err(Error::Render) + .map_err(Error::Render), } } @@ -2666,7 +2772,7 @@ where fn map_texture<'c>( &mut self, texture_mapping: &'c Self::TextureMapping, - ) -> Result<&'c [u8], <Self as Renderer>::Error> { + ) -> Result<&'c [u8], <Self as RendererSuper>::Error> { match texture_mapping { MultiTextureMapping(TextureMappingInternal::Either(target_mapping)) => self .target @@ -2685,62 +2791,52 @@ where } } -impl<R: GraphicsApi, T: GraphicsApi, BlitTarget> Blit<BlitTarget> for MultiRenderer<'_, '_, R, T> +impl<R: GraphicsApi, T: GraphicsApi> Blit for MultiRenderer<'_, '_, R, T> where - <R::Device as ApiDevice>::Renderer: Blit<BlitTarget> + Bind<BlitTarget>, - <T::Device as ApiDevice>::Renderer: Blit<BlitTarget> + Bind<BlitTarget>, + <R::Device as ApiDevice>::Renderer: Blit, + <T::Device as ApiDevice>::Renderer: Blit, // We need this because the Renderer-impl does and Blit requires Renderer R: 'static, R::Error: 'static, T::Error: 'static, <R::Device as ApiDevice>::Renderer: Bind<Dmabuf> + ExportMem + ImportDma + ImportMem, <T::Device as ApiDevice>::Renderer: ImportDma + ImportMem, - <<R::Device as ApiDevice>::Renderer as Renderer>::TextureId: Clone + Send, - <<R::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, - <<T::Device as ApiDevice>::Renderer as Renderer>::Error: 'static, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::TextureId: Clone + Send, + <<R::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, + <<T::Device as ApiDevice>::Renderer as RendererSuper>::Error: 'static, { - #[instrument(level = "trace", parent = &self.span, skip(self, to))] - #[profiling::function] - fn blit_to( - &mut self, - to: BlitTarget, - src: Rectangle<i32, Physical>, - dst: Rectangle<i32, Physical>, - filter: TextureFilter, - ) -> Result<(), <Self as Renderer>::Error> { - if let Some(target) = self.target.as_mut() { - target - .device - .renderer_mut() - .blit_to(to, src, dst, filter) - .map_err(Error::Target) - } else { - self.render - .renderer_mut() - .blit_to(to, src, dst, filter) - .map_err(Error::Render) - } - } - - #[instrument(level = "trace", parent = &self.span, skip(self, from))] + #[instrument(level = "trace", parent = &self.span, skip(self, from, to))] #[profiling::function] - fn blit_from( + fn blit( &mut self, - from: BlitTarget, + from: &MultiFramebuffer<'_, R, T>, + to: &mut MultiFramebuffer<'_, R, T>, src: Rectangle<i32, Physical>, dst: Rectangle<i32, Physical>, filter: TextureFilter, - ) -> Result<(), <Self as Renderer>::Error> { + ) -> Result<(), <Self as RendererSuper>::Error> { if let Some(target) = self.target.as_mut() { + let MultiFramebufferInternal::Target(ref from_fb) = &from.0 else { + unreachable!() + }; + let MultiFramebufferInternal::Target(ref mut to_fb) = &mut to.0 else { + unreachable!() + }; target .device .renderer_mut() - .blit_from(from, src, dst, filter) + .blit(from_fb, to_fb, src, dst, filter) .map_err(Error::Target) } else { + let MultiFramebufferInternal::Render(ref from_fb) = &from.0 else { + unreachable!() + }; + let MultiFramebufferInternal::Render(ref mut to_fb) = &mut to.0 else { + unreachable!() + }; self.render .renderer_mut() - .blit_from(from, src, dst, filter) + .blit(from_fb, to_fb, src, dst, filter) .map_err(Error::Render) } } diff --git a/src/backend/renderer/pixman/mod.rs b/src/backend/renderer/pixman/mod.rs index ff225d8cab16..c8db62b383e2 100644 --- a/src/backend/renderer/pixman/mod.rs +++ b/src/backend/renderer/pixman/mod.rs @@ -34,7 +34,7 @@ use wayland_server::protocol::wl_buffer; use super::ImportEgl; use super::{ sync::SyncPoint, Bind, Color32F, DebugFlags, ExportMem, Frame, ImportDma, ImportMem, Offscreen, Renderer, - Texture, TextureFilter, TextureMapping, Unbind, + RendererSuper, Texture, TextureFilter, TextureMapping, }; mod error; @@ -62,21 +62,13 @@ const SUPPORTED_FORMATS: &[DrmFourcc] = &[ DrmFourcc::Abgr2101010, ]; +/// A framebuffer of an [`PixmanRenderer`]. #[derive(Debug)] -enum PixmanTarget { - Image { dmabuf: Dmabuf, image: PixmanImage }, - RenderBuffer(PixmanRenderBuffer), -} - -/// Offscreen render buffer +pub struct PixmanTarget<'a>(PixmanTargetInternal<'a>); #[derive(Debug)] -pub struct PixmanRenderBuffer(pixman::Image<'static, 'static>); - -impl From<pixman::Image<'static, 'static>> for PixmanRenderBuffer { - #[inline] - fn from(value: pixman::Image<'static, 'static>) -> Self { - Self(value) - } +enum PixmanTargetInternal<'a> { + Dmabuf { dmabuf: &'a Dmabuf, image: PixmanImage }, + Image(&'a mut pixman::Image<'static, 'static>), } #[derive(Debug)] @@ -239,8 +231,9 @@ impl Texture for PixmanTexture { /// Handle to the currently rendered frame during [`PixmanRenderer::render`](Renderer::render). #[derive(Debug)] -pub struct PixmanFrame<'frame> { +pub struct PixmanFrame<'frame, 'buffer> { renderer: &'frame mut PixmanRenderer, + target: &'frame mut PixmanTarget<'buffer>, transform: Transform, output_size: Size<i32, Physical>, @@ -249,7 +242,7 @@ pub struct PixmanFrame<'frame> { finished: AtomicBool, } -impl PixmanFrame<'_> { +impl PixmanFrame<'_, '_> { fn draw_solid_color( &mut self, dst: Rectangle<i32, Physical>, @@ -259,12 +252,12 @@ impl PixmanFrame<'_> { debug: DebugFlags, ) -> Result<(), PixmanError> { let mut binding; - let target_image = match self.renderer.target.as_mut().ok_or(PixmanError::NoTargetBound)? { - PixmanTarget::Image { image, .. } => { + let target_image = match &mut self.target.0 { + PixmanTargetInternal::Dmabuf { image, .. } => { binding = image.0.image.lock().unwrap(); &mut *binding } - PixmanTarget::RenderBuffer(b) => &mut b.0, + PixmanTargetInternal::Image(b) => b, }; let solid = pixman::Solid::new(color.components()).map_err(|_| PixmanError::Unsupported)?; @@ -323,7 +316,7 @@ impl PixmanFrame<'_> { } } -impl Frame for PixmanFrame<'_> { +impl Frame for PixmanFrame<'_, '_> { type Error = PixmanError; type TextureId = PixmanTexture; @@ -370,12 +363,12 @@ impl Frame for PixmanFrame<'_> { alpha: f32, ) -> Result<(), Self::Error> { let mut binding; - let target_image = match self.renderer.target.as_mut().ok_or(PixmanError::NoTargetBound)? { - PixmanTarget::Image { image, .. } => { + let target_image = match &mut self.target.0 { + PixmanTargetInternal::Dmabuf { image, .. } => { binding = image.0.image.lock().unwrap(); &mut *binding } - PixmanTarget::RenderBuffer(b) => &mut b.0, + PixmanTargetInternal::Image(b) => b, }; let src_image_accessor = texture.accessor()?; @@ -626,16 +619,14 @@ impl Frame for PixmanFrame<'_> { } } -impl PixmanFrame<'_> { +impl PixmanFrame<'_, '_> { #[profiling::function] fn finish_internal(&mut self) -> Result<SyncPoint, PixmanError> { if self.finished.swap(true, Ordering::SeqCst) { return Ok(SyncPoint::signaled()); } - if let PixmanTarget::Image { dmabuf, .. } = - self.renderer.target.as_ref().ok_or(PixmanError::NoTargetBound)? - { + if let PixmanTargetInternal::Dmabuf { dmabuf, .. } = &self.target.0 { dmabuf .sync_plane( 0, @@ -648,7 +639,7 @@ impl PixmanFrame<'_> { } } -impl Drop for PixmanFrame<'_> { +impl Drop for PixmanFrame<'_, '_> { fn drop(&mut self) { match self.finish_internal() { Ok(sync) => { @@ -664,7 +655,6 @@ impl Drop for PixmanFrame<'_> { /// A renderer utilizing pixman #[derive(Debug)] pub struct PixmanRenderer { - target: Option<PixmanTarget>, downscale_filter: TextureFilter, upscale_filter: TextureFilter, debug_flags: DebugFlags, @@ -680,7 +670,6 @@ impl PixmanRenderer { pub fn new() -> Result<Self, PixmanError> { let tint = pixman::Solid::new([0.0, 0.2, 0.0, 0.2]).map_err(|_| PixmanError::Unsupported)?; Ok(Self { - target: None, downscale_filter: TextureFilter::Linear, upscale_filter: TextureFilter::Linear, debug_flags: DebugFlags::empty(), @@ -783,13 +772,17 @@ impl PixmanRenderer { } } -impl Renderer for PixmanRenderer { +impl RendererSuper for PixmanRenderer { type Error = PixmanError; - type TextureId = PixmanTexture; + type Framebuffer<'buffer> = PixmanTarget<'buffer>; + type Frame<'frame, 'buffer> + = PixmanFrame<'frame, 'buffer> + where + 'buffer: 'frame; +} - type Frame<'frame> = PixmanFrame<'frame>; - +impl Renderer for PixmanRenderer { fn id(&self) -> usize { 0 } @@ -812,15 +805,19 @@ impl Renderer for PixmanRenderer { self.debug_flags } - #[profiling::function] - fn render( - &mut self, + //#[profiling::function] + fn render<'frame, 'buffer>( + &'frame mut self, + target: &'frame mut PixmanTarget<'buffer>, output_size: Size<i32, Physical>, dst_transform: Transform, - ) -> Result<PixmanFrame<'_>, Self::Error> { + ) -> Result<PixmanFrame<'frame, 'buffer>, Self::Error> + where + 'buffer: 'frame, + { self.cleanup(); - if let PixmanTarget::Image { dmabuf, .. } = self.target.as_ref().ok_or(PixmanError::NoTargetBound)? { + if let PixmanTargetInternal::Dmabuf { dmabuf, .. } = &target.0 { dmabuf .sync_plane( 0, @@ -830,6 +827,7 @@ impl Renderer for PixmanRenderer { } Ok(PixmanFrame { renderer: self, + target, transform: dst_transform, output_size, @@ -856,7 +854,7 @@ impl ImportMem for PixmanRenderer { format: drm_fourcc::DrmFourcc, size: Size<i32, BufferCoords>, flipped: bool, - ) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error> { + ) -> Result<Self::TextureId, Self::Error> { let format = pixman::FormatCode::try_from(format).map_err(|_| PixmanError::UnsupportedPixelFormat(format))?; let image = pixman::Image::new(format, size.w as usize, size.h as usize, false) @@ -883,10 +881,10 @@ impl ImportMem for PixmanRenderer { #[profiling::function] fn update_memory( &mut self, - texture: &<Self as Renderer>::TextureId, + texture: &Self::TextureId, data: &[u8], region: Rectangle<i32, BufferCoords>, - ) -> Result<(), <Self as Renderer>::Error> { + ) -> Result<(), Self::Error> { #[cfg(feature = "wayland_frontend")] if texture.0 .0.buffer.is_some() { return Err(PixmanError::ImportFailed); @@ -969,39 +967,38 @@ impl ExportMem for PixmanRenderer { #[profiling::function] fn copy_framebuffer( &mut self, + target: &PixmanTarget<'_>, region: Rectangle<i32, BufferCoords>, format: DrmFourcc, - ) -> Result<Self::TextureMapping, <Self as Renderer>::Error> { + ) -> Result<Self::TextureMapping, Self::Error> { let format_code = pixman::FormatCode::try_from(format).map_err(|_| PixmanError::UnsupportedPixelFormat(format))?; let mut copy_image = pixman::Image::new(format_code, region.size.w as usize, region.size.h as usize, false) .map_err(|_| PixmanError::Unsupported)?; - if let Some(target) = self.target.as_ref() { - let binding; - let target_image = match target { - PixmanTarget::Image { dmabuf, image } => { - dmabuf.sync_plane(0, DmabufSyncFlags::START | DmabufSyncFlags::READ)?; - binding = image.0.image.lock().unwrap(); - &*binding - } - PixmanTarget::RenderBuffer(b) => &b.0, - }; + let binding; + let target_image = match &target.0 { + PixmanTargetInternal::Dmabuf { dmabuf, image } => { + dmabuf.sync_plane(0, DmabufSyncFlags::START | DmabufSyncFlags::READ)?; + binding = image.0.image.lock().unwrap(); + &*binding + } + PixmanTargetInternal::Image(b) => *b, + }; - copy_image.composite32( - Operation::Src, - target_image, - None, - region.loc.into(), - (0, 0), - (0, 0), - region.size.into(), - ); - if let PixmanTarget::Image { dmabuf, .. } = target { - dmabuf.sync_plane(0, DmabufSyncFlags::END | DmabufSyncFlags::READ)?; - }; - } + copy_image.composite32( + Operation::Src, + target_image, + None, + region.loc.into(), + (0, 0), + (0, 0), + region.size.into(), + ); + if let PixmanTargetInternal::Dmabuf { dmabuf, .. } = &target.0 { + dmabuf.sync_plane(0, DmabufSyncFlags::END | DmabufSyncFlags::READ)?; + }; Ok(PixmanMapping(copy_image)) } @@ -1041,7 +1038,7 @@ impl ExportMem for PixmanRenderer { fn map_texture<'a>( &mut self, texture_mapping: &'a Self::TextureMapping, - ) -> Result<&'a [u8], <Self as Renderer>::Error> { + ) -> Result<&'a [u8], Self::Error> { Ok(unsafe { std::slice::from_raw_parts( texture_mapping.0.data() as *const u8, @@ -1075,7 +1072,7 @@ impl ImportEgl for PixmanRenderer { _buffer: &wl_buffer::WlBuffer, _surface: Option<&SurfaceData>, _damage: &[Rectangle<i32, BufferCoords>], - ) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error> { + ) -> Result<Self::TextureId, Self::Error> { Err(PixmanError::Unsupported) } } @@ -1134,7 +1131,7 @@ impl ImportDma for PixmanRenderer { &mut self, dmabuf: &Dmabuf, _damage: Option<&[Rectangle<i32, BufferCoords>]>, - ) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error> { + ) -> Result<Self::TextureId, Self::Error> { if let Some(image) = self.existing_dmabuf(dmabuf) { return Ok(PixmanTexture(image)); }; @@ -1162,17 +1159,9 @@ impl ImportDma for PixmanRenderer { #[cfg(feature = "wayland_frontend")] impl ImportDmaWl for PixmanRenderer {} -impl Unbind for PixmanRenderer { - #[profiling::function] - fn unbind(&mut self) -> Result<(), <Self as Renderer>::Error> { - self.target = None; - Ok(()) - } -} - impl Bind<Dmabuf> for PixmanRenderer { - #[profiling::function] - fn bind(&mut self, target: Dmabuf) -> Result<(), <Self as Renderer>::Error> { + //#[profiling::function] + fn bind<'a>(&mut self, target: &'a mut Dmabuf) -> Result<PixmanTarget<'a>, Self::Error> { let existing_image = self .buffers .iter() @@ -1181,7 +1170,7 @@ impl Bind<Dmabuf> for PixmanRenderer { .0 .dmabuf .as_ref() - .and_then(|map| map.dmabuf.upgrade().map(|buf| buf == target)) + .and_then(|map| map.dmabuf.upgrade().map(|buf| buf == *target)) .unwrap_or(false) }) .cloned(); @@ -1189,16 +1178,15 @@ impl Bind<Dmabuf> for PixmanRenderer { let image = if let Some(image) = existing_image { image } else { - let image = self.import_dmabuf(&target, DmabufMappingMode::READ | DmabufMappingMode::WRITE)?; + let image = self.import_dmabuf(target, DmabufMappingMode::READ | DmabufMappingMode::WRITE)?; self.buffers.push(image.clone()); image }; - self.target = Some(PixmanTarget::Image { + Ok(PixmanTarget(PixmanTargetInternal::Dmabuf { dmabuf: target, image, - }); - Ok(()) + })) } fn supported_formats(&self) -> Option<FormatSet> { @@ -1216,26 +1204,25 @@ impl Bind<Dmabuf> for PixmanRenderer { } } -impl Offscreen<PixmanRenderBuffer> for PixmanRenderer { +impl Offscreen<Image<'static, 'static>> for PixmanRenderer { #[profiling::function] fn create_buffer( &mut self, format: DrmFourcc, size: Size<i32, BufferCoords>, - ) -> Result<PixmanRenderBuffer, <Self as Renderer>::Error> { + ) -> Result<Image<'static, 'static>, Self::Error> { let format_code = FormatCode::try_from(format).map_err(|_| PixmanError::UnsupportedPixelFormat(format))?; let image = pixman::Image::new(format_code, size.w as usize, size.h as usize, true) .map_err(|_| PixmanError::Unsupported)?; - Ok(PixmanRenderBuffer::from(image)) + Ok(image) } } -impl Bind<PixmanRenderBuffer> for PixmanRenderer { - #[profiling::function] - fn bind(&mut self, target: PixmanRenderBuffer) -> Result<(), <Self as Renderer>::Error> { - self.target = Some(PixmanTarget::RenderBuffer(target)); - Ok(()) +impl Bind<Image<'static, 'static>> for PixmanRenderer { + //#[profiling::function] + fn bind<'a>(&mut self, target: &'a mut Image<'static, 'static>) -> Result<PixmanTarget<'a>, Self::Error> { + Ok(PixmanTarget(PixmanTargetInternal::Image(target))) } fn supported_formats(&self) -> Option<FormatSet> { diff --git a/src/backend/renderer/test.rs b/src/backend/renderer/test.rs index c0a28471b743..c5b2efdaaca8 100644 --- a/src/backend/renderer/test.rs +++ b/src/backend/renderer/test.rs @@ -18,7 +18,8 @@ use crate::{ backend::{ allocator::{dmabuf::Dmabuf, Fourcc}, renderer::{ - sync::SyncPoint, DebugFlags, Frame, ImportDma, ImportMem, Renderer, Texture, TextureFilter, + sync::SyncPoint, DebugFlags, Frame, ImportDma, ImportMem, Renderer, RendererSuper, Texture, + TextureFilter, }, SwapBuffersError, }, @@ -27,22 +28,10 @@ use crate::{ use super::Color32F; -#[derive(Debug)] -pub struct DummyRenderer {} - -impl DummyRenderer { - pub fn new() -> DummyRenderer { - DummyRenderer {} - } -} +#[derive(Debug, Default)] +pub struct DummyRenderer; -impl Default for DummyRenderer { - fn default() -> Self { - Self::new() - } -} - -/// Error returned by the TestRenderer +/// Error returned by the DummyRenderer #[derive(thiserror::Error, Debug)] pub enum DummyError { /// Error accessing shm buffer @@ -61,20 +50,31 @@ impl From<DummyError> for SwapBuffersError { } } -impl Renderer for DummyRenderer { +impl RendererSuper for DummyRenderer { type Error = DummyError; type TextureId = DummyTexture; - type Frame<'a> = DummyFrame; + type Frame<'frame, 'buffer> + = DummyFrame + where + 'buffer: 'frame, + Self: 'frame; + type Framebuffer<'buffer> = DummyFramebuffer; +} +impl Renderer for DummyRenderer { fn id(&self) -> usize { 0 } - fn render( - &mut self, + fn render<'frame, 'buffer>( + &'frame mut self, + _target: &'frame mut DummyFramebuffer, _size: Size<i32, Physical>, _dst_transform: Transform, - ) -> Result<DummyFrame, Self::Error> { + ) -> Result<DummyFrame, Self::Error> + where + 'buffer: 'frame, + { Ok(DummyFrame {}) } @@ -104,16 +104,16 @@ impl ImportMem for DummyRenderer { _format: Fourcc, _size: Size<i32, Buffer>, _flipped: bool, - ) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error> { + ) -> Result<Self::TextureId, Self::Error> { unimplemented!() } fn update_memory( &mut self, - _texture: &<Self as Renderer>::TextureId, + _texture: &Self::TextureId, _data: &[u8], _region: Rectangle<i32, Buffer>, - ) -> Result<(), <Self as Renderer>::Error> { + ) -> Result<(), Self::Error> { unimplemented!() } @@ -129,7 +129,7 @@ impl ImportMemWl for DummyRenderer { buffer: &wl_buffer::WlBuffer, surface: Option<&SurfaceData>, _damage: &[Rectangle<i32, Buffer>], - ) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error> { + ) -> Result<Self::TextureId, Self::Error> { use std::ptr; use wayland::shm::with_buffer_contents; let ret = with_buffer_contents(buffer, |ptr, len, data| { @@ -167,7 +167,7 @@ impl ImportDma for DummyRenderer { &mut self, _dmabuf: &Dmabuf, _damage: Option<&[Rectangle<i32, Buffer>]>, - ) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error> { + ) -> Result<Self::TextureId, Self::Error> { unimplemented!() } } @@ -198,7 +198,7 @@ impl ImportEgl for DummyRenderer { _buffer: &wl_buffer::WlBuffer, _surface: Option<&wayland::compositor::SurfaceData>, _damage: &[Rectangle<i32, Buffer>], - ) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error> { + ) -> Result<Self::TextureId, Self::Error> { unimplemented!() } } @@ -206,6 +206,9 @@ impl ImportEgl for DummyRenderer { #[cfg(feature = "wayland_frontend")] impl ImportDmaWl for DummyRenderer {} +#[derive(Debug)] +pub struct DummyFramebuffer; + #[derive(Debug)] pub struct DummyFrame {} diff --git a/src/backend/renderer/utils/wayland.rs b/src/backend/renderer/utils/wayland.rs index e72e221facec..08dedbf8c6df 100644 --- a/src/backend/renderer/utils/wayland.rs +++ b/src/backend/renderer/utils/wayland.rs @@ -319,9 +319,9 @@ impl RendererSurfaceState { pub fn texture<R>(&self, id: usize) -> Option<&R::TextureId> where R: Renderer, - <R as Renderer>::TextureId: 'static, + R::TextureId: 'static, { - let texture_id = (TypeId::of::<<R as Renderer>::TextureId>(), id); + let texture_id = (TypeId::of::<R::TextureId>(), id); self.textures.get(&texture_id).and_then(|e| e.downcast_ref()) } @@ -486,13 +486,13 @@ where /// to let smithay handle buffer management. #[instrument(level = "trace", skip_all)] #[profiling::function] -pub fn import_surface<R>(renderer: &mut R, states: &SurfaceData) -> Result<(), <R as Renderer>::Error> +pub fn import_surface<R>(renderer: &mut R, states: &SurfaceData) -> Result<(), R::Error> where R: Renderer + ImportAll, - <R as Renderer>::TextureId: 'static, + R::TextureId: 'static, { if let Some(data) = states.data_map.get::<RendererSurfaceStateUserData>() { - let texture_id = (TypeId::of::<<R as Renderer>::TextureId>(), renderer.id()); + let texture_id = (TypeId::of::<R::TextureId>(), renderer.id()); let mut data_ref = data.lock().unwrap(); let data = &mut *data_ref; @@ -537,15 +537,15 @@ where /// to let smithay handle buffer management. #[instrument(level = "trace", skip_all)] #[profiling::function] -pub fn import_surface_tree<R>(renderer: &mut R, surface: &WlSurface) -> Result<(), <R as Renderer>::Error> +pub fn import_surface_tree<R>(renderer: &mut R, surface: &WlSurface) -> Result<(), R::Error> where R: Renderer + ImportAll, - <R as Renderer>::TextureId: 'static, + R::TextureId: 'static, { let scale = 1.0; let location: Point<f64, Physical> = (0.0, 0.0).into(); - let texture_id = (TypeId::of::<<R as Renderer>::TextureId>(), renderer.id()); + let texture_id = (TypeId::of::<R::TextureId>(), renderer.id()); let mut result = Ok(()); with_surface_tree_downward( surface, @@ -592,15 +592,15 @@ where /// to let smithay handle buffer management. #[instrument(level = "trace", skip(frame, scale, elements))] #[profiling::function] -pub fn draw_render_elements<'a, R, S, E>( - frame: &mut <R as Renderer>::Frame<'a>, +pub fn draw_render_elements<R, S, E>( + frame: &mut R::Frame<'_, '_>, scale: S, elements: &[E], damage: &[Rectangle<i32, Physical>], -) -> Result<Option<Vec<Rectangle<i32, Physical>>>, <R as Renderer>::Error> +) -> Result<Option<Vec<Rectangle<i32, Physical>>>, R::Error> where R: Renderer, - <R as Renderer>::TextureId: 'static, + R::TextureId: 'static, S: Into<Scale<f64>>, E: RenderElement<R>, { diff --git a/src/backend/winit/mod.rs b/src/backend/winit/mod.rs index 9458eb39629d..a82511b52f34 100644 --- a/src/backend/winit/mod.rs +++ b/src/backend/winit/mod.rs @@ -10,7 +10,7 @@ //! you want on the initialization of the backend. These functions will provide you //! with two objects: //! -//! - a [`WinitGraphicsBackend`], which can give you an implementation of a [`Renderer`] +//! - a [`WinitGraphicsBackend`], which can give you an implementation of a [`Renderer`](crate::backend::renderer::Renderer) //! (or even [`GlesRenderer`]) through its `renderer` method in addition to further //! functionality to access and manage the created winit-window. //! - a [`WinitEventLoop`], which dispatches some [`WinitEvent`] from the host graphics server. @@ -19,7 +19,6 @@ //! two traits for the winit backend. use std::io::Error as IoError; -use std::rc::Rc; use std::sync::Arc; use std::time::Duration; @@ -59,14 +58,12 @@ mod input; pub use self::input::*; -use super::renderer::Renderer; - /// Create a new [`WinitGraphicsBackend`], which implements the -/// [`Renderer`] trait and a corresponding [`WinitEventLoop`]. +/// [`Renderer`](crate::backend::renderer::Renderer) trait and a corresponding [`WinitEventLoop`]. pub fn init<R>() -> Result<(WinitGraphicsBackend<R>, WinitEventLoop), Error> where - R: From<GlesRenderer> + Bind<Rc<EGLSurface>>, - crate::backend::SwapBuffersError: From<<R as Renderer>::Error>, + R: From<GlesRenderer> + Bind<EGLSurface>, + crate::backend::SwapBuffersError: From<R::Error>, { init_from_attributes( WinitWindow::default_attributes() @@ -76,15 +73,15 @@ where ) } -/// Create a new [`WinitGraphicsBackend`], which implements the [`Renderer`] +/// Create a new [`WinitGraphicsBackend`], which implements the [`Renderer`](crate::backend::renderer::Renderer) /// trait, from a given [`WindowAttributes`] struct and a corresponding /// [`WinitEventLoop`]. pub fn init_from_attributes<R>( attributes: WindowAttributes, ) -> Result<(WinitGraphicsBackend<R>, WinitEventLoop), Error> where - R: From<GlesRenderer> + Bind<Rc<EGLSurface>>, - crate::backend::SwapBuffersError: From<<R as Renderer>::Error>, + R: From<GlesRenderer> + Bind<EGLSurface>, + crate::backend::SwapBuffersError: From<R::Error>, { init_from_attributes_with_gl_attr( attributes, @@ -97,7 +94,7 @@ where ) } -/// Create a new [`WinitGraphicsBackend`], which implements the [`Renderer`] +/// Create a new [`WinitGraphicsBackend`], which implements the [`Renderer`](crate::backend::renderer::Renderer) /// trait, from a given [`WindowAttributes`] struct, as well as given /// [`GlAttributes`] for further customization of the rendering pipeline and a /// corresponding [`WinitEventLoop`]. @@ -106,8 +103,8 @@ pub fn init_from_attributes_with_gl_attr<R>( gl_attributes: GlAttributes, ) -> Result<(WinitGraphicsBackend<R>, WinitEventLoop), Error> where - R: From<GlesRenderer> + Bind<Rc<EGLSurface>>, - crate::backend::SwapBuffersError: From<<R as Renderer>::Error>, + R: From<GlesRenderer> + Bind<EGLSurface>, + crate::backend::SwapBuffersError: From<R::Error>, { let span = info_span!("backend_winit", window = tracing::field::Empty); let _guard = span.enter(); @@ -182,7 +179,6 @@ where (display, context, surface, is_x11) }; - let egl = Rc::new(surface); let renderer = unsafe { GlesRenderer::new(context)?.into() }; let damage_tracking = display.supports_damage(); @@ -196,7 +192,7 @@ where window: window.clone(), span: span.clone(), _display: display, - egl_surface: egl, + egl_surface: surface, damage_tracking, bind_size: None, renderer, @@ -246,7 +242,7 @@ pub struct WinitGraphicsBackend<R> { renderer: R, // The display isn't used past this point but must be kept alive. _display: EGLDisplay, - egl_surface: Rc<EGLSurface>, + egl_surface: EGLSurface, window: Arc<WinitWindow>, damage_tracking: bool, bind_size: Option<Size<i32, Physical>>, @@ -255,8 +251,8 @@ pub struct WinitGraphicsBackend<R> { impl<R> WinitGraphicsBackend<R> where - R: Bind<Rc<EGLSurface>>, - crate::backend::SwapBuffersError: From<<R as Renderer>::Error>, + R: Bind<EGLSurface>, + crate::backend::SwapBuffersError: From<R::Error>, { /// Window size of the underlying window pub fn window_size(&self) -> Size<i32, Physical> { @@ -282,7 +278,7 @@ where /// Bind the underlying window to the underlying renderer. #[instrument(level = "trace", parent = &self.span, skip(self))] #[profiling::function] - pub fn bind(&mut self) -> Result<(), crate::backend::SwapBuffersError> { + pub fn bind(&mut self) -> Result<(&mut R, R::Framebuffer<'_>), crate::backend::SwapBuffersError> { // NOTE: we must resize before making the current context current, otherwise the back // buffer will be latched. Some nvidia drivers may not like it, but a lot of wayland // software does the order that way due to mesa latching back buffer on each @@ -293,17 +289,17 @@ where } self.bind_size = Some(window_size); - self.renderer.bind(self.egl_surface.clone())?; + let fb = self.renderer.bind(&mut self.egl_surface).map_err(Into::into)?; - Ok(()) + Ok((&mut self.renderer, fb)) } /// Retrieve the underlying `EGLSurface` for advanced operations /// /// **Note:** Don't carelessly use this to manually bind the renderer to the surface, /// `WinitGraphicsBackend::bind` transparently handles window resizes for you. - pub fn egl_surface(&self) -> Rc<EGLSurface> { - self.egl_surface.clone() + pub fn egl_surface(&self) -> &EGLSurface { + &self.egl_surface } /// Retrieve the buffer age of the current backbuffer of the window. diff --git a/src/desktop/space/element/mod.rs b/src/desktop/space/element/mod.rs index 749ea61ca394..ab65858634e6 100644 --- a/src/desktop/space/element/mod.rs +++ b/src/desktop/space/element/mod.rs @@ -169,7 +169,7 @@ impl< E: AsRenderElements<R>, > AsRenderElements<R> for SpaceElements<'a, E> where - <R as Renderer>::TextureId: Clone + Texture + 'static, + R::TextureId: Clone + Texture + 'static, <E as AsRenderElements<R>>::RenderElement: 'a, SpaceRenderElements<R, <E as AsRenderElements<R>>::RenderElement>: From<Wrap<<E as AsRenderElements<R>>::RenderElement>>, diff --git a/src/desktop/space/element/wayland.rs b/src/desktop/space/element/wayland.rs index de9e3d0d64d3..59f05745a5f5 100644 --- a/src/desktop/space/element/wayland.rs +++ b/src/desktop/space/element/wayland.rs @@ -32,7 +32,7 @@ impl IsAlive for SurfaceTree { impl<R> AsRenderElements<R> for SurfaceTree where R: Renderer + ImportAll, - <R as Renderer>::TextureId: Clone + 'static, + R::TextureId: Clone + 'static, { type RenderElement = WaylandSurfaceRenderElement<R>; diff --git a/src/desktop/space/mod.rs b/src/desktop/space/mod.rs index ee93e289f30a..a2dad8a0297d 100644 --- a/src/desktop/space/mod.rs +++ b/src/desktop/space/mod.rs @@ -386,7 +386,7 @@ impl<E: SpaceElement + PartialEq> Space<E> { alpha: f32, ) -> Vec<<E as AsRenderElements<R>>::RenderElement> where - <R as Renderer>::TextureId: Texture + 'static, + R::TextureId: Texture + 'static, E: AsRenderElements<R>, <E as AsRenderElements<R>>::RenderElement: 'a, { @@ -426,7 +426,7 @@ impl<E: SpaceElement + PartialEq> Space<E> { alpha: f32, ) -> Result<Vec<SpaceRenderElements<R, <E as AsRenderElements<R>>::RenderElement>>, OutputError> where - <R as Renderer>::TextureId: Clone + Texture + 'static, + R::TextureId: Clone + Texture + 'static, E: AsRenderElements<R>, <E as AsRenderElements<R>>::RenderElement: 'a, SpaceRenderElements<R, <E as AsRenderElements<R>>::RenderElement>: @@ -588,7 +588,7 @@ pub fn space_render_elements< alpha: f32, ) -> Result<Vec<SpaceRenderElements<R, <E as AsRenderElements<R>>::RenderElement>>, OutputNoMode> where - <R as Renderer>::TextureId: Clone + Texture + 'static, + R::TextureId: Clone + Texture + 'static, <E as AsRenderElements<R>>::RenderElement: 'a, SpaceRenderElements<R, <E as AsRenderElements<R>>::RenderElement>: From<Wrap<<E as AsRenderElements<R>>::RenderElement>>, @@ -675,6 +675,7 @@ pub fn render_output< >( output: &Output, renderer: &mut R, + framebuffer: &mut R::Framebuffer<'_>, alpha: f32, age: usize, spaces: S, @@ -683,7 +684,7 @@ pub fn render_output< clear_color: impl Into<Color32F>, ) -> Result<RenderOutputResult<'d>, OutputDamageTrackerError<R::Error>> where - <R as Renderer>::TextureId: Clone + Texture + 'static, + R::TextureId: Clone + Texture + 'static, <E as AsRenderElements<R>>::RenderElement: 'a, SpaceRenderElements<R, <E as AsRenderElements<R>>::RenderElement>: From<Wrap<<E as AsRenderElements<R>>::RenderElement>>, @@ -700,5 +701,5 @@ where render_elements.extend(custom_elements.iter().map(OutputRenderElements::Custom)); render_elements.extend(space_render_elements.into_iter().map(OutputRenderElements::Space)); - damage_tracker.render_output(renderer, age, &render_elements, clear_color) + damage_tracker.render_output(renderer, framebuffer, age, &render_elements, clear_color) } diff --git a/src/desktop/space/wayland/layer.rs b/src/desktop/space/wayland/layer.rs index 4c59e186ece7..4b28fdb0e4f9 100644 --- a/src/desktop/space/wayland/layer.rs +++ b/src/desktop/space/wayland/layer.rs @@ -13,7 +13,7 @@ use crate::{ impl<R> AsRenderElements<R> for LayerSurface where R: Renderer + ImportAll, - <R as Renderer>::TextureId: Clone + 'static, + R::TextureId: Clone + 'static, { type RenderElement = WaylandSurfaceRenderElement<R>; diff --git a/src/desktop/space/wayland/window.rs b/src/desktop/space/wayland/window.rs index 0390aaa588cc..c85e3007dff1 100644 --- a/src/desktop/space/wayland/window.rs +++ b/src/desktop/space/wayland/window.rs @@ -87,7 +87,7 @@ impl SpaceElement for Window { impl<R> AsRenderElements<R> for Window where R: Renderer + ImportAll, - <R as Renderer>::TextureId: Clone + 'static, + R::TextureId: Clone + 'static, { type RenderElement = WaylandSurfaceRenderElement<R>; diff --git a/src/desktop/space/wayland/x11.rs b/src/desktop/space/wayland/x11.rs index 1711894d971e..e82e0d525a9c 100644 --- a/src/desktop/space/wayland/x11.rs +++ b/src/desktop/space/wayland/x11.rs @@ -97,7 +97,7 @@ impl SpaceElement for X11Surface { impl<R> crate::backend::renderer::element::AsRenderElements<R> for X11Surface where R: Renderer + ImportAll, - <R as Renderer>::TextureId: Clone + 'static, + R::TextureId: Clone + 'static, { type RenderElement = WaylandSurfaceRenderElement<R>; diff --git a/wlcs_anvil/src/main_loop.rs b/wlcs_anvil/src/main_loop.rs index fa40b6f8379b..d0f9e728e3dd 100644 --- a/wlcs_anvil/src/main_loop.rs +++ b/wlcs_anvil/src/main_loop.rs @@ -7,7 +7,11 @@ use std::{ use smithay::{ backend::{ input::ButtonState, - renderer::{damage::OutputDamageTracker, element::AsRenderElements, test::DummyRenderer}, + renderer::{ + damage::OutputDamageTracker, + element::AsRenderElements, + test::{DummyFramebuffer, DummyRenderer}, + }, }, input::pointer::{ ButtonEvent, CursorImageAttributes, CursorImageStatus, MotionEvent, RelativeMotionEvent, @@ -62,7 +66,8 @@ pub fn run(channel: Channel<WlcsEvent>) { }) .unwrap(); - let mut renderer = DummyRenderer::new(); + let mut renderer = DummyRenderer; + let mut framebuffer = DummyFramebuffer; let mode = Mode { size: (800, 600).into(), @@ -150,6 +155,7 @@ pub fn run(channel: Channel<WlcsEvent>) { &state.space, elements, &mut renderer, + &mut framebuffer, &mut damage_tracker, 0, false,