From 18886965673e3f9d5faec0bafd09f68be2d9db45 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Wed, 10 Apr 2024 08:53:35 +0400 Subject: 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 --- src/layout/closing_window.rs | 2 +- src/layout/mod.rs | 20 ++++----- src/layout/tile.rs | 101 +++++++++++++++++++++++++------------------ 3 files changed, 67 insertions(+), 56 deletions(-) (limited to 'src/layout') diff --git a/src/layout/closing_window.rs b/src/layout/closing_window.rs index ec565ebf..3de0d51f 100644 --- a/src/layout/closing_window.rs +++ b/src/layout/closing_window.rs @@ -59,7 +59,7 @@ impl ClosingWindow { #[allow(clippy::too_many_arguments)] pub fn new>( renderer: &mut GlesRenderer, - snapshot: RenderSnapshot, + snapshot: RenderSnapshot, scale: i32, center: Point, pos: Point, diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 18870025..073ae804 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -36,10 +36,11 @@ use std::time::Duration; use niri_config::{CenterFocusedColumn, Config, Struts}; use niri_ipc::SizeChange; -use smithay::backend::renderer::element::solid::SolidColorRenderElement; +use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement}; use smithay::backend::renderer::element::surface::WaylandSurfaceRenderElement; +use smithay::backend::renderer::element::texture::TextureBuffer; use smithay::backend::renderer::element::Id; -use smithay::backend::renderer::gles::GlesRenderer; +use smithay::backend::renderer::gles::{GlesRenderer, GlesTexture}; use smithay::output::Output; use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface; use smithay::utils::{Logical, Point, Scale, Size, Transform}; @@ -48,9 +49,8 @@ use self::monitor::Monitor; pub use self::monitor::MonitorRenderElement; use self::workspace::{compute_working_area, Column, ColumnWidth, OutputId, Workspace}; use crate::niri_render_elements; -use crate::render_helpers::primary_gpu_texture::PrimaryGpuTextureRenderElement; use crate::render_helpers::renderer::NiriRenderer; -use crate::render_helpers::{RenderSnapshot, RenderTarget}; +use crate::render_helpers::{BakedBuffer, RenderSnapshot, RenderTarget}; use crate::utils::output_size; use crate::window::ResolvedWindowRules; @@ -67,12 +67,8 @@ niri_render_elements! { } } -niri_render_elements! { - LayoutElementSnapshotRenderElements => { - Texture = PrimaryGpuTextureRenderElement, - SolidColor = SolidColorRenderElement, - } -} +pub type LayoutElementRenderSnapshot = + RenderSnapshot>, BakedBuffer>; pub trait LayoutElement { /// Type that can be used as a unique ID of this element. @@ -110,7 +106,7 @@ pub trait LayoutElement { target: RenderTarget, ) -> Vec>; - fn take_last_render(&self) -> RenderSnapshot; + fn take_last_render(&self) -> LayoutElementRenderSnapshot; fn request_size(&self, size: Size); fn request_fullscreen(&self, size: Size); @@ -1930,7 +1926,7 @@ mod tests { vec![] } - fn take_last_render(&self) -> RenderSnapshot { + fn take_last_render(&self) -> LayoutElementRenderSnapshot { RenderSnapshot::default() } diff --git a/src/layout/tile.rs b/src/layout/tile.rs index fb825184..5cc89073 100644 --- a/src/layout/tile.rs +++ b/src/layout/tile.rs @@ -3,22 +3,19 @@ use std::rc::Rc; use std::time::Duration; use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement}; -use smithay::backend::renderer::element::utils::{ - Relocate, RelocateRenderElement, RescaleRenderElement, -}; +use smithay::backend::renderer::element::utils::RescaleRenderElement; use smithay::backend::renderer::element::{Element, Kind}; use smithay::backend::renderer::gles::GlesRenderer; use smithay::utils::{Logical, Point, Rectangle, Scale, Size}; use super::focus_ring::{FocusRing, FocusRingRenderElement}; -use super::{ - LayoutElement, LayoutElementRenderElement, LayoutElementSnapshotRenderElements, Options, -}; +use super::{LayoutElement, LayoutElementRenderElement, Options}; use crate::animation::Animation; use crate::niri_render_elements; use crate::render_helpers::offscreen::OffscreenRenderElement; +use crate::render_helpers::primary_gpu_texture::PrimaryGpuTextureRenderElement; use crate::render_helpers::renderer::NiriRenderer; -use crate::render_helpers::{RenderSnapshot, RenderTarget}; +use crate::render_helpers::{RenderSnapshot, RenderTarget, ToRenderElement}; /// Toplevel window with decorations. #[derive(Debug)] @@ -65,7 +62,7 @@ niri_render_elements! { niri_render_elements! { TileSnapshotRenderElement => { - LayoutElement = RelocateRenderElement, + Texture = PrimaryGpuTextureRenderElement, FocusRing = FocusRingRenderElement, SolidColor = SolidColorRenderElement, } @@ -417,52 +414,70 @@ impl Tile { } } - pub fn take_snapshot_for_close_anim( + fn render_snapshot( &self, renderer: &mut GlesRenderer, scale: Scale, view_size: Size, - ) -> RenderSnapshot { - let snapshot = self.window.take_last_render(); - if snapshot.contents.is_empty() { - return RenderSnapshot::default(); - } + contents: Vec, + ) -> Vec + where + C: ToRenderElement>, + { + let alpha = if self.is_fullscreen { + 1. + } else { + self.window.rules().opacity.unwrap_or(1.).clamp(0., 1.) + }; - let mut process = |contents| { - let mut rv = vec![]; + let mut rv = vec![]; - let buf_pos = - (self.window_loc() + self.window.buf_loc()).to_physical_precise_round(scale); - for elem in contents { - let elem = RelocateRenderElement::from_element(elem, buf_pos, Relocate::Relative); - rv.push(elem.into()); - } + for baked in contents { + let elem = baked.to_render_element(self.window_loc(), scale, alpha, Kind::Unspecified); + rv.push(elem.into()); + } - if let Some(width) = self.effective_border_width() { - rv.extend( - self.border - .render(renderer, Point::from((width, width)), scale, view_size) - .map(Into::into), - ); - } + if let Some(width) = self.effective_border_width() { + rv.extend( + self.border + .render(renderer, Point::from((width, width)), scale, view_size) + .map(Into::into), + ); + } - if self.is_fullscreen { - let elem = SolidColorRenderElement::from_buffer( - &self.fullscreen_backdrop, - Point::from((0, 0)), - scale, - 1., - Kind::Unspecified, - ); - rv.push(elem.into()); - } + if self.is_fullscreen { + let elem = SolidColorRenderElement::from_buffer( + &self.fullscreen_backdrop, + Point::from((0, 0)), + scale, + 1., + Kind::Unspecified, + ); + rv.push(elem.into()); + } - rv - }; + rv + } + + pub fn take_snapshot_for_close_anim( + &self, + renderer: &mut GlesRenderer, + scale: Scale, + view_size: Size, + ) -> RenderSnapshot { + let snapshot = self.window.take_last_render(); + if snapshot.contents.is_empty() { + return RenderSnapshot::default(); + } RenderSnapshot { - contents: process(snapshot.contents), - blocked_out_contents: process(snapshot.blocked_out_contents), + contents: self.render_snapshot(renderer, scale, view_size, snapshot.contents), + blocked_out_contents: self.render_snapshot( + renderer, + scale, + view_size, + snapshot.blocked_out_contents, + ), block_out_from: snapshot.block_out_from, } } -- cgit