diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-04-10 08:53:35 +0400 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-04-10 09:14:04 +0400 |
| commit | 18886965673e3f9d5faec0bafd09f68be2d9db45 (patch) | |
| tree | 4cfc7fbf7c5b9b87fca7c47e672a6c47cc06855a /src/render_helpers/surface.rs | |
| parent | b9e789619f91d4b542618cb19b0fa27cd2e052c7 (diff) | |
| download | niri-18886965673e3f9d5faec0bafd09f68be2d9db45.tar.gz niri-18886965673e3f9d5faec0bafd09f68be2d9db45.tar.bz2 niri-18886965673e3f9d5faec0bafd09f68be2d9db45.zip | |
Reimplement window closing anim in an efficient way
- Keep a root surface cache to be accessible in surface destroyed()
- Only snapshot during / right before closing, rather than every frame
- Store textures rather than elements to handle scale and alpha properly
Diffstat (limited to 'src/render_helpers/surface.rs')
| -rw-r--r-- | src/render_helpers/surface.rs | 108 |
1 files changed, 37 insertions, 71 deletions
diff --git a/src/render_helpers/surface.rs b/src/render_helpers/surface.rs index ae7ffc32..21141b30 100644 --- a/src/render_helpers/surface.rs +++ b/src/render_helpers/surface.rs @@ -1,41 +1,25 @@ -use smithay::backend::renderer::element::surface::WaylandSurfaceRenderElement; -use smithay::backend::renderer::element::texture::{TextureBuffer, TextureRenderElement}; -use smithay::backend::renderer::element::Kind; -use smithay::backend::renderer::gles::GlesRenderer; +use smithay::backend::renderer::element::texture::TextureBuffer; +use smithay::backend::renderer::gles::{GlesRenderer, GlesTexture}; use smithay::backend::renderer::utils::{import_surface, RendererSurfaceStateUserData}; use smithay::backend::renderer::Renderer as _; use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface; -use smithay::utils::{Physical, Point, Scale}; +use smithay::utils::{Logical, Point}; use smithay::wayland::compositor::{with_surface_tree_downward, TraversalAction}; -use super::primary_gpu_texture::PrimaryGpuTextureRenderElement; -use super::renderer::NiriRenderer; -use crate::layout::{LayoutElementRenderElement, LayoutElementSnapshotRenderElements}; +use super::BakedBuffer; -/// Renders elements from a surface tree, as well as saves them as textures into `storage`. -/// -/// Saved textures are based at (0, 0) to facilitate later offscreening. This is why the location -/// argument is split into `location` and `offset`: the former is ignored for saved textures, but -/// the latter isn't (for things like popups). -#[allow(clippy::too_many_arguments)] -pub fn render_and_save_from_surface_tree<R: NiriRenderer>( - renderer: &mut R, +/// Renders elements from a surface tree as textures into `storage`. +pub fn render_snapshot_from_surface_tree( + renderer: &mut GlesRenderer, surface: &WlSurface, - location: Point<f64, Physical>, - offset: Point<f64, Physical>, - scale: Scale<f64>, - alpha: f32, - kind: Kind, - elements: &mut Vec<LayoutElementRenderElement<R>>, - storage: &mut Option<&mut Vec<LayoutElementSnapshotRenderElements>>, + location: Point<i32, Logical>, + storage: &mut Vec<BakedBuffer<TextureBuffer<GlesTexture>>>, ) { - let _span = tracy_client::span!("render_and_save_from_surface_tree"); - - let base_pos = location; + let _span = tracy_client::span!("render_snapshot_from_surface_tree"); with_surface_tree_downward( surface, - location + offset, + location, |_, states, location| { let mut location = *location; let data = states.data_map.get::<RendererSurfaceStateUserData>(); @@ -44,7 +28,7 @@ pub fn render_and_save_from_surface_tree<R: NiriRenderer>( let data = &*data.borrow(); if let Some(view) = data.view() { - location += view.offset.to_f64().to_physical(scale); + location += view.offset; TraversalAction::DoChildren(location) } else { TraversalAction::SkipChildren @@ -53,62 +37,44 @@ pub fn render_and_save_from_surface_tree<R: NiriRenderer>( TraversalAction::SkipChildren } }, - |surface, states, location| { + |_, states, location| { let mut location = *location; let data = states.data_map.get::<RendererSurfaceStateUserData>(); if let Some(data) = data { if let Some(view) = data.borrow().view() { - location += view.offset.to_f64().to_physical(scale); + location += view.offset; } else { return; } - let elem = match WaylandSurfaceRenderElement::from_surface( - renderer, surface, states, location, alpha, kind, - ) { - Ok(elem) => elem, - Err(err) => { - warn!("failed to import surface: {err:?}"); - return; - } - }; - - elements.push(elem.into()); - - if let Some(storage) = storage { - let renderer = renderer.as_gles_renderer(); - // FIXME (possibly in Smithay): this causes a re-upload for shm textures. - if let Err(err) = import_surface(renderer, states) { - warn!("failed to import surface: {err:?}"); - return; - } + if let Err(err) = import_surface(renderer, states) { + warn!("failed to import surface: {err:?}"); + return; + } - let data = data.borrow(); - let view = data.view().unwrap(); - let Some(texture) = data.texture::<GlesRenderer>(renderer.id()) else { - return; - }; + let data = data.borrow(); + let view = data.view().unwrap(); + let Some(texture) = data.texture::<GlesRenderer>(renderer.id()) else { + return; + }; - let buffer = TextureBuffer::from_texture( - renderer, - texture.clone(), - data.buffer_scale(), - data.buffer_transform(), - None, - ); + let buffer = TextureBuffer::from_texture( + renderer, + texture.clone(), + data.buffer_scale(), + data.buffer_transform(), + None, + ); - let elem = TextureRenderElement::from_texture_buffer( - location - base_pos, - &buffer, - Some(alpha), - Some(view.src), - Some(view.dst), - kind, - ); + let baked = BakedBuffer { + buffer, + location, + src: Some(view.src), + dst: Some(view.dst), + }; - storage.push(PrimaryGpuTextureRenderElement(elem).into()); - } + storage.push(baked); } }, |_, _, _| true, |
