diff --git a/anvil/src/drawing.rs b/anvil/src/drawing.rs index ef73764d84f8..67a3e1a38289 100644 --- a/anvil/src/drawing.rs +++ b/anvil/src/drawing.rs @@ -66,7 +66,7 @@ impl std::fmt::Debug for PointerRenderElement { } } -impl AsRenderElements for PointerElement +impl AsRenderElements for PointerElement where R: Renderer + ImportAll + ImportMem, { diff --git a/anvil/src/shell/element.rs b/anvil/src/shell/element.rs index c4ddccd6037f..16d3d5036874 100644 --- a/anvil/src/shell/element.rs +++ b/anvil/src/shell/element.rs @@ -381,7 +381,7 @@ impl std::fmt::Debug for WindowRenderElement { impl AsRenderElements for WindowElement where R: Renderer + ImportAll + ImportMem, - ::TextureId: Texture + 'static, + ::TextureId: Clone + Texture + 'static, { type RenderElement = WindowRenderElement; diff --git a/src/backend/renderer/element/surface.rs b/src/backend/renderer/element/surface.rs index 258378ef0a47..36299a19c8d5 100644 --- a/src/backend/renderer/element/surface.rs +++ b/src/backend/renderer/element/surface.rs @@ -218,17 +218,17 @@ //! } //! ``` -use std::{fmt, marker::PhantomData}; +use std::fmt; use tracing::{instrument, warn}; use wayland_server::protocol::wl_surface; use crate::{ backend::renderer::{ - utils::{DamageSet, RendererSurfaceStateUserData}, + utils::{Buffer, DamageSet, DamageSnapshot, RendererSurfaceStateUserData, SurfaceView}, Frame, ImportAll, Renderer, Texture, }, - utils::{Buffer, Physical, Point, Rectangle, Scale, Size, Transform}, + utils::{Buffer as BufferCoords, Logical, Physical, Point, Rectangle, Scale, Size, Transform}, wayland::compositor::{self, SurfaceData, TraversalAction}, }; @@ -247,7 +247,7 @@ pub fn render_elements_from_surface_tree( ) -> Vec where R: Renderer + ImportAll, - ::TextureId: 'static, + ::TextureId: Clone + 'static, E: From>, { let location = location.into().to_f64(); @@ -290,7 +290,8 @@ where match WaylandSurfaceRenderElement::from_surface( renderer, surface, states, location, alpha, kind, ) { - Ok(surface) => surfaces.push(surface.into()), + Ok(Some(surface)) => surfaces.push(surface.into()), + Ok(None) => {} // surface is not mapped Err(err) => { warn!("Failed to import surface: {}", err); } @@ -305,21 +306,27 @@ where } /// A single surface render element -pub struct WaylandSurfaceRenderElement { +pub struct WaylandSurfaceRenderElement { id: Id, location: Point, alpha: f32, - surface: wl_surface::WlSurface, - renderer_type: PhantomData, kind: Kind, + + view: Option, + buffer: Option, + buffer_scale: i32, + buffer_transform: Transform, + buffer_dimensions: Option>, + damage: DamageSnapshot, + opaque_regions: Vec>, + texture: Option, } -impl fmt::Debug for WaylandSurfaceRenderElement { +impl fmt::Debug for WaylandSurfaceRenderElement { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("WaylandSurfaceRenderElement") .field("id", &self.id) .field("location", &self.location) - .field("surface", &self.surface) .finish() } } @@ -334,33 +341,48 @@ impl WaylandSurfaceRenderElement { location: Point, alpha: f32, kind: Kind, - ) -> Result::Error> + ) -> Result, ::Error> where - ::TextureId: 'static, + ::TextureId: Clone + 'static, { let id = Id::from_wayland_resource(surface); crate::backend::renderer::utils::import_surface(renderer, states)?; - Ok(Self { + let Some(data_ref) = states.data_map.get::() else { + return Ok(None); + }; + let data = data_ref.borrow(); + + Ok(Some(Self { id, location, alpha, - surface: surface.clone(), - renderer_type: PhantomData, kind, - }) + view: data.view(), + buffer: data.buffer().cloned(), + buffer_scale: data.buffer_scale, + buffer_transform: data.buffer_transform, + buffer_dimensions: data.buffer_dimensions, + damage: data.damage.snapshot(), + opaque_regions: data.opaque_regions.clone(), + texture: data.texture::(renderer.id()).cloned(), + })) } fn size(&self, scale: impl Into>) -> Size { - compositor::with_states(&self.surface, |states| { - let data = states.data_map.get::(); - data.and_then(|d| d.borrow().view()).map(|surface_view| { + self.view + .map(|surface_view| { ((surface_view.dst.to_f64().to_physical(scale).to_point() + self.location).to_i32_round() - self.location.to_i32_round()) .to_size() }) - }) - .unwrap_or_default() + .unwrap_or_default() + } + + fn buffer_size(&self) -> Option> { + self.buffer_dimensions + .as_ref() + .map(|dim| dim.to_logical(self.buffer_scale, self.buffer_transform)) } } @@ -370,94 +392,73 @@ impl Element for WaylandSurfaceRenderElement { } fn current_commit(&self) -> CommitCounter { - compositor::with_states(&self.surface, |states| { - let data = states.data_map.get::(); - data.map(|d| d.borrow().current_commit()) - }) - .unwrap_or_default() + self.damage.current_commit() } fn geometry(&self, scale: Scale) -> Rectangle { Rectangle::from_loc_and_size(self.location.to_i32_round(), self.size(scale)) } - fn src(&self) -> Rectangle { - compositor::with_states(&self.surface, |states| { - let data = states.data_map.get::(); - if let Some(data) = data { - let data = data.borrow(); - - if let Some(view) = data.view() { - Some(view.src.to_buffer( - data.buffer_scale as f64, - data.buffer_transform, - &data.buffer_size().unwrap().to_f64(), - )) - } else { - None - } - } else { - None - } - }) - .unwrap_or_default() + fn src(&self) -> Rectangle { + self.view + .map(|view| { + view.src.to_buffer( + self.buffer_scale as f64, + self.buffer_transform, + &self.buffer_size().unwrap().to_f64(), + ) + }) + .unwrap_or_default() } fn transform(&self) -> Transform { - compositor::with_states(&self.surface, |states| { - let data = states.data_map.get::(); - data.map(|d| d.borrow().buffer_transform) - }) - .unwrap_or_default() + self.buffer_transform } fn damage_since(&self, scale: Scale, commit: Option) -> DamageSet { let dst_size = self.size(scale); - compositor::with_states(&self.surface, |states| { - let data = states.data_map.get::(); - data.and_then(|d| { - let data = d.borrow(); - if let Some(surface_view) = data.view() { - let damage = data - .damage_since(commit) - .iter() - .filter_map(|rect| { - rect.to_f64() - // first bring the damage into logical space - // Note: We use f64 for this as the damage could - // be not dividable by the buffer scale without - // a rest - .to_logical( - data.buffer_scale as f64, - data.buffer_transform, - &data.buffer_dimensions.unwrap().to_f64(), - ) - // then crop by the surface view (viewporter for example could define a src rect) - .intersection(surface_view.src) - // move and scale the cropped rect (viewporter could define a dst size) - .map(|rect| surface_view.rect_to_global(rect).to_i32_up::()) - // now bring the damage to physical space - .map(|rect| { - // We calculate the scale between to rounded - // surface size and the scaled surface size - // and use it to scale the damage to the rounded - // surface size by multiplying the output scale - // with the result. - let surface_scale = - dst_size.to_f64() / surface_view.dst.to_f64().to_physical(scale); - rect.to_physical_precise_up(surface_scale * scale) - }) - }) - .collect::>(); - - Some(damage) - } else { - None - } + self.view + .map(|surface_view| { + self.damage + .damage_since(commit) + .unwrap_or_else(|| { + self.buffer_dimensions + .as_ref() + .map(|size| DamageSet::from_slice(&[Rectangle::from_loc_and_size((0, 0), *size)])) + .unwrap_or_default() + }) + .iter() + .filter_map(|rect| { + rect.to_f64() + // first bring the damage into logical space + // Note: We use f64 for this as the damage could + // be not dividable by the buffer scale without + // a rest + .to_logical( + self.buffer_scale as f64, + self.buffer_transform, + &self.buffer_dimensions.unwrap().to_f64(), + ) + // then crop by the surface view (viewporter for example could define a src rect) + .intersection(surface_view.src) + // move and scale the cropped rect (viewporter could define a dst size) + .map(|rect| surface_view.rect_to_global(rect).to_i32_up::()) + // now bring the damage to physical space + .map(|rect| { + // We calculate the scale between to rounded + // surface size and the scaled surface size + // and use it to scale the damage to the rounded + // surface size by multiplying the output scale + // with the result. + let surface_scale = + dst_size.to_f64() / surface_view.dst.to_f64().to_physical(scale); + rect.to_physical_precise_up(surface_scale * scale) + }) + }) + .collect::>() }) .unwrap_or_default() - }) } fn opaque_regions(&self, scale: Scale) -> Vec> { @@ -465,27 +466,20 @@ impl Element for WaylandSurfaceRenderElement { return Vec::new(); } - compositor::with_states(&self.surface, |states| { - let data = states.data_map.get::(); - data.map(|d| { - let data = d.borrow(); - data.opaque_regions() - .map(|r| { - r.iter() - .map(|r| { - let loc = r.loc.to_physical_precise_round(scale); - let size = ((r.size.to_f64().to_physical(scale).to_point() + self.location) - .to_i32_round() - - self.location.to_i32_round()) - .to_size(); - Rectangle::from_loc_and_size(loc, size) - }) - .collect::>() - }) - .unwrap_or_default() + if self.view.is_none() { + return Vec::new(); + } + + self.opaque_regions + .iter() + .map(|r| { + let loc = r.loc.to_physical_precise_round(scale); + let size = ((r.size.to_f64().to_physical(scale).to_point() + self.location).to_i32_round() + - self.location.to_i32_round()) + .to_size(); + Rectangle::from_loc_and_size(loc, size) }) - .unwrap_or_default() - }) + .collect::>() } fn alpha(&self) -> f32 { @@ -503,11 +497,7 @@ where ::TextureId: Texture + 'static, { fn underlying_storage(&self, _renderer: &mut R) -> Option { - compositor::with_states(&self.surface, |states| { - let data = states.data_map.get::(); - data.and_then(|d| d.borrow().buffer().cloned()) - .map(UnderlyingStorage::Wayland) - }) + self.buffer.clone().map(UnderlyingStorage::Wayland) } #[instrument(level = "trace", skip(frame))] @@ -515,30 +505,15 @@ where fn draw<'a>( &self, frame: &mut ::Frame<'a>, - src: Rectangle, + src: Rectangle, dst: Rectangle, damage: &[Rectangle], ) -> Result<(), R::Error> { - compositor::with_states(&self.surface, |states| { - let data = states.data_map.get::(); - if let Some(data) = data { - let data = data.borrow(); - - if let Some(texture) = data.texture::(frame.id()) { - frame.render_texture_from_to( - texture, - src, - dst, - damage, - data.buffer_transform, - self.alpha, - )?; - } else { - warn!("trying to render texture from different renderer"); - } - } - + if let Some(texture) = &self.texture { + frame.render_texture_from_to(texture, src, dst, damage, self.buffer_transform, self.alpha) + } else { + warn!("trying to render texture from different renderer"); Ok(()) - }) + } } } diff --git a/src/backend/renderer/utils/wayland.rs b/src/backend/renderer/utils/wayland.rs index 3cf08eb82321..86adb44912a7 100644 --- a/src/backend/renderer/utils/wayland.rs +++ b/src/backend/renderer/utils/wayland.rs @@ -476,7 +476,7 @@ where /// Imports buffers of a surface and its subsurfaces using a given [`Renderer`]. /// -/// This (or `import_surface`) need to be called before`draw_render_elements`, if used later. +/// This (or `import_surface`) need to be called before `draw_render_elements`, if used later. /// /// Note: This will do nothing, if you are not using /// [`crate::backend::renderer::utils::on_commit_buffer_handler`] diff --git a/src/desktop/space/element/mod.rs b/src/desktop/space/element/mod.rs index 27c5ccdee7a6..f89310bc8dab 100644 --- a/src/desktop/space/element/mod.rs +++ b/src/desktop/space/element/mod.rs @@ -167,7 +167,7 @@ impl< E: AsRenderElements, > AsRenderElements for SpaceElements<'a, E> where - ::TextureId: Texture + 'static, + ::TextureId: Clone + Texture + 'static, >::RenderElement: 'a, SpaceRenderElements>::RenderElement>: From>::RenderElement>>, diff --git a/src/desktop/space/element/wayland.rs b/src/desktop/space/element/wayland.rs index 84ec1a78ea32..cd77347a2d59 100644 --- a/src/desktop/space/element/wayland.rs +++ b/src/desktop/space/element/wayland.rs @@ -31,7 +31,7 @@ impl IsAlive for SurfaceTree { impl AsRenderElements for SurfaceTree where R: Renderer + ImportAll, - ::TextureId: 'static, + ::TextureId: Clone + 'static, { type RenderElement = WaylandSurfaceRenderElement; diff --git a/src/desktop/space/mod.rs b/src/desktop/space/mod.rs index 0a675051c84a..dcaaf48f77db 100644 --- a/src/desktop/space/mod.rs +++ b/src/desktop/space/mod.rs @@ -424,7 +424,7 @@ impl Space { alpha: f32, ) -> Result>::RenderElement>>, OutputError> where - ::TextureId: Texture + 'static, + ::TextureId: Clone + Texture + 'static, E: AsRenderElements, >::RenderElement: 'a, SpaceRenderElements>::RenderElement>: @@ -585,7 +585,7 @@ pub fn space_render_elements< alpha: f32, ) -> Result>::RenderElement>>, OutputNoMode> where - ::TextureId: Texture + 'static, + ::TextureId: Clone + Texture + 'static, >::RenderElement: 'a, SpaceRenderElements>::RenderElement>: From>::RenderElement>>, @@ -680,7 +680,7 @@ pub fn render_output< clear_color: [f32; 4], ) -> Result, OutputDamageTrackerError> where - ::TextureId: Texture + 'static, + ::TextureId: Clone + Texture + 'static, >::RenderElement: 'a, SpaceRenderElements>::RenderElement>: From>::RenderElement>>, diff --git a/src/desktop/space/wayland/layer.rs b/src/desktop/space/wayland/layer.rs index 27ba3b11a081..4c59e186ece7 100644 --- a/src/desktop/space/wayland/layer.rs +++ b/src/desktop/space/wayland/layer.rs @@ -13,7 +13,7 @@ use crate::{ impl AsRenderElements for LayerSurface where R: Renderer + ImportAll, - ::TextureId: 'static, + ::TextureId: Clone + 'static, { type RenderElement = WaylandSurfaceRenderElement; diff --git a/src/desktop/space/wayland/window.rs b/src/desktop/space/wayland/window.rs index 1639842738c4..07c0b9f72d0e 100644 --- a/src/desktop/space/wayland/window.rs +++ b/src/desktop/space/wayland/window.rs @@ -87,7 +87,7 @@ impl SpaceElement for Window { impl AsRenderElements for Window where R: Renderer + ImportAll, - ::TextureId: 'static, + ::TextureId: Clone + 'static, { type RenderElement = WaylandSurfaceRenderElement; diff --git a/src/desktop/space/wayland/x11.rs b/src/desktop/space/wayland/x11.rs index fea59e2a0ac8..aca6a21e52e8 100644 --- a/src/desktop/space/wayland/x11.rs +++ b/src/desktop/space/wayland/x11.rs @@ -94,7 +94,7 @@ impl SpaceElement for X11Surface { impl crate::backend::renderer::element::AsRenderElements for X11Surface where R: Renderer + ImportAll, - ::TextureId: 'static, + ::TextureId: Clone + 'static, { type RenderElement = WaylandSurfaceRenderElement;