aboutsummaryrefslogtreecommitdiff
path: root/src/render_helpers/surface.rs
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-04-10 08:53:35 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2024-04-10 09:14:04 +0400
commit18886965673e3f9d5faec0bafd09f68be2d9db45 (patch)
tree4cfc7fbf7c5b9b87fca7c47e672a6c47cc06855a /src/render_helpers/surface.rs
parentb9e789619f91d4b542618cb19b0fa27cd2e052c7 (diff)
downloadniri-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.rs108
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,