Unify Animation- and RenderSnapshot

This commit is contained in:
Ivan Molodetskikh
2024-04-13 14:16:07 +04:00
parent 71be19b234
commit 9d5f1c7ef7
10 changed files with 188 additions and 187 deletions
+8 -10
View File
@@ -2,11 +2,9 @@ use std::cell::RefCell;
use std::cmp::{max, min}; use std::cmp::{max, min};
use std::rc::Rc; use std::rc::Rc;
use niri::layout::{ use niri::layout::{LayoutElement, LayoutElementRenderElement, LayoutElementRenderSnapshot};
AnimationSnapshot, LayoutElement, LayoutElementRenderElement, LayoutElementRenderSnapshot,
};
use niri::render_helpers::renderer::NiriRenderer; use niri::render_helpers::renderer::NiriRenderer;
use niri::render_helpers::{RenderSnapshot, RenderTarget}; use niri::render_helpers::RenderTarget;
use niri::window::ResolvedWindowRules; use niri::window::ResolvedWindowRules;
use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement}; use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement};
use smithay::backend::renderer::element::{Id, Kind}; use smithay::backend::renderer::element::{Id, Kind};
@@ -175,10 +173,6 @@ impl LayoutElement for TestWindow {
] ]
} }
fn take_last_render(&self) -> LayoutElementRenderSnapshot {
RenderSnapshot::default()
}
fn request_size(&mut self, size: Size<i32, Logical>, _animate: bool) { fn request_size(&mut self, size: Size<i32, Logical>, _animate: bool) {
self.inner.borrow_mut().requested_size = Some(size); self.inner.borrow_mut().requested_size = Some(size);
self.inner.borrow_mut().pending_fullscreen = false; self.inner.borrow_mut().pending_fullscreen = false;
@@ -233,11 +227,15 @@ impl LayoutElement for TestWindow {
&EMPTY &EMPTY
} }
fn animation_snapshot(&self) -> Option<&AnimationSnapshot> { fn take_unmap_snapshot(&self) -> Option<LayoutElementRenderSnapshot> {
None None
} }
fn take_animation_snapshot(&mut self) -> Option<AnimationSnapshot> { fn animation_snapshot(&self) -> Option<&LayoutElementRenderSnapshot> {
None
}
fn take_animation_snapshot(&mut self) -> Option<LayoutElementRenderSnapshot> {
None None
} }
} }
+1 -1
View File
@@ -304,7 +304,7 @@ impl CompositorHandler for State {
if let Some(root) = self.niri.root_surface.get(surface) { if let Some(root) = self.niri.root_surface.get(surface) {
if let Some((mapped, _)) = self.niri.layout.find_window_and_output(root) { if let Some((mapped, _)) = self.niri.layout.find_window_and_output(root) {
self.backend.with_primary_renderer(|renderer| { self.backend.with_primary_renderer(|renderer| {
mapped.render_and_store_snapshot(renderer); mapped.store_unmap_snapshot_if_empty(renderer);
}); });
} }
} }
+4 -4
View File
@@ -387,7 +387,7 @@ impl XdgShellHandler for State {
let output = output.clone(); let output = output.clone();
self.backend.with_primary_renderer(|renderer| { self.backend.with_primary_renderer(|renderer| {
mapped.render_and_store_snapshot(renderer); mapped.store_unmap_snapshot_if_empty(renderer);
}); });
self.backend.with_primary_renderer(|renderer| { self.backend.with_primary_renderer(|renderer| {
self.niri self.niri
@@ -845,11 +845,11 @@ pub fn add_mapped_toplevel_pre_commit_hook(toplevel: &ToplevelSurface) -> HookId
if got_unmapped { if got_unmapped {
state.backend.with_primary_renderer(|renderer| { state.backend.with_primary_renderer(|renderer| {
mapped.render_and_store_snapshot(renderer); mapped.store_unmap_snapshot_if_empty(renderer);
}); });
} else { } else {
// The toplevel remains mapped; clear any cached render snapshot. // The toplevel remains mapped; clear any stored unmap snapshot.
let _ = mapped.take_last_render(); let _ = mapped.take_unmap_snapshot();
if animate { if animate {
state.backend.with_primary_renderer(|renderer| { state.backend.with_primary_renderer(|renderer| {
+2 -1
View File
@@ -14,7 +14,8 @@ use smithay::utils::{Logical, Point, Scale, Transform};
use crate::animation::Animation; use crate::animation::Animation;
use crate::niri_render_elements; use crate::niri_render_elements;
use crate::render_helpers::primary_gpu_texture::PrimaryGpuTextureRenderElement; use crate::render_helpers::primary_gpu_texture::PrimaryGpuTextureRenderElement;
use crate::render_helpers::{render_to_encompassing_texture, RenderSnapshot, RenderTarget}; use crate::render_helpers::snapshot::RenderSnapshot;
use crate::render_helpers::{render_to_encompassing_texture, RenderTarget};
#[derive(Debug)] #[derive(Debug)]
pub struct ClosingWindow { pub struct ClosingWindow {
+12 -20
View File
@@ -50,7 +50,8 @@ pub use self::monitor::MonitorRenderElement;
use self::workspace::{compute_working_area, Column, ColumnWidth, OutputId, Workspace}; use self::workspace::{compute_working_area, Column, ColumnWidth, OutputId, Workspace};
use crate::niri_render_elements; use crate::niri_render_elements;
use crate::render_helpers::renderer::NiriRenderer; use crate::render_helpers::renderer::NiriRenderer;
use crate::render_helpers::{BakedBuffer, RenderSnapshot, RenderTarget}; use crate::render_helpers::snapshot::RenderSnapshot;
use crate::render_helpers::{BakedBuffer, RenderTarget};
use crate::utils::output_size; use crate::utils::output_size;
use crate::window::ResolvedWindowRules; use crate::window::ResolvedWindowRules;
@@ -73,15 +74,6 @@ niri_render_elements! {
pub type LayoutElementRenderSnapshot = pub type LayoutElementRenderSnapshot =
RenderSnapshot<BakedBuffer<TextureBuffer<GlesTexture>>, BakedBuffer<SolidColorBuffer>>; RenderSnapshot<BakedBuffer<TextureBuffer<GlesTexture>>, BakedBuffer<SolidColorBuffer>>;
/// Snapshot of an element for animation.
#[derive(Debug)]
pub struct AnimationSnapshot {
/// Snapshot of the render.
pub render: LayoutElementRenderSnapshot,
/// Visual size of the element at the point of the snapshot.
pub size: Size<i32, Logical>,
}
pub trait LayoutElement { pub trait LayoutElement {
/// Type that can be used as a unique ID of this element. /// Type that can be used as a unique ID of this element.
type Id: PartialEq; type Id: PartialEq;
@@ -118,8 +110,6 @@ pub trait LayoutElement {
target: RenderTarget, target: RenderTarget,
) -> Vec<LayoutElementRenderElement<R>>; ) -> Vec<LayoutElementRenderElement<R>>;
fn take_last_render(&self) -> LayoutElementRenderSnapshot;
fn request_size(&mut self, size: Size<i32, Logical>, animate: bool); fn request_size(&mut self, size: Size<i32, Logical>, animate: bool);
fn request_fullscreen(&self, size: Size<i32, Logical>); fn request_fullscreen(&self, size: Size<i32, Logical>);
fn min_size(&self) -> Size<i32, Logical>; fn min_size(&self) -> Size<i32, Logical>;
@@ -150,8 +140,10 @@ pub trait LayoutElement {
/// Runs periodic clean-up tasks. /// Runs periodic clean-up tasks.
fn refresh(&self); fn refresh(&self);
fn animation_snapshot(&self) -> Option<&AnimationSnapshot>; fn take_unmap_snapshot(&self) -> Option<LayoutElementRenderSnapshot>;
fn take_animation_snapshot(&mut self) -> Option<AnimationSnapshot>;
fn animation_snapshot(&self) -> Option<&LayoutElementRenderSnapshot>;
fn take_animation_snapshot(&mut self) -> Option<LayoutElementRenderSnapshot>;
} }
#[derive(Debug)] #[derive(Debug)]
@@ -1966,10 +1958,6 @@ mod tests {
vec![] vec![]
} }
fn take_last_render(&self) -> LayoutElementRenderSnapshot {
RenderSnapshot::default()
}
fn request_size(&mut self, size: Size<i32, Logical>, _animate: bool) { fn request_size(&mut self, size: Size<i32, Logical>, _animate: bool) {
self.0.requested_size.set(Some(size)); self.0.requested_size.set(Some(size));
self.0.pending_fullscreen.set(false); self.0.pending_fullscreen.set(false);
@@ -2024,11 +2012,15 @@ mod tests {
&EMPTY &EMPTY
} }
fn animation_snapshot(&self) -> Option<&AnimationSnapshot> { fn take_unmap_snapshot(&self) -> Option<LayoutElementRenderSnapshot> {
None None
} }
fn take_animation_snapshot(&mut self) -> Option<AnimationSnapshot> { fn animation_snapshot(&self) -> Option<&LayoutElementRenderSnapshot> {
None
}
fn take_animation_snapshot(&mut self) -> Option<LayoutElementRenderSnapshot> {
None None
} }
} }
+14 -95
View File
@@ -1,19 +1,17 @@
use std::cell::OnceCell;
use std::cmp::max; use std::cmp::max;
use std::rc::Rc; use std::rc::Rc;
use std::time::Duration; use std::time::Duration;
use niri_config::BlockOutFrom;
use smithay::backend::allocator::Fourcc; use smithay::backend::allocator::Fourcc;
use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement}; use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement};
use smithay::backend::renderer::element::utils::RescaleRenderElement; use smithay::backend::renderer::element::utils::RescaleRenderElement;
use smithay::backend::renderer::element::{Element, Kind}; use smithay::backend::renderer::element::{Element, Kind};
use smithay::backend::renderer::gles::{GlesRenderer, GlesTexture}; use smithay::backend::renderer::gles::GlesRenderer;
use smithay::utils::{Logical, Physical, Point, Rectangle, Scale, Size, Transform}; use smithay::utils::{Logical, Point, Rectangle, Scale, Size, Transform};
use super::focus_ring::{FocusRing, FocusRingRenderElement}; use super::focus_ring::{FocusRing, FocusRingRenderElement};
use super::{ use super::{
AnimationSnapshot, LayoutElement, LayoutElementRenderElement, Options, LayoutElement, LayoutElementRenderElement, LayoutElementRenderSnapshot, Options,
RESIZE_ANIMATION_THRESHOLD, RESIZE_ANIMATION_THRESHOLD,
}; };
use crate::animation::Animation; use crate::animation::Animation;
@@ -23,9 +21,8 @@ use crate::render_helpers::offscreen::OffscreenRenderElement;
use crate::render_helpers::primary_gpu_texture::PrimaryGpuTextureRenderElement; use crate::render_helpers::primary_gpu_texture::PrimaryGpuTextureRenderElement;
use crate::render_helpers::renderer::NiriRenderer; use crate::render_helpers::renderer::NiriRenderer;
use crate::render_helpers::shaders::Shaders; use crate::render_helpers::shaders::Shaders;
use crate::render_helpers::{ use crate::render_helpers::snapshot::RenderSnapshot;
render_to_encompassing_texture, RenderSnapshot, RenderTarget, ToRenderElement, use crate::render_helpers::{render_to_encompassing_texture, RenderTarget, ToRenderElement};
};
/// Toplevel window with decorations. /// Toplevel window with decorations.
#[derive(Debug)] #[derive(Debug)]
@@ -96,10 +93,7 @@ niri_render_elements! {
struct ResizeAnimation { struct ResizeAnimation {
anim: Animation, anim: Animation,
size_from: Size<i32, Logical>, size_from: Size<i32, Logical>,
snapshot: AnimationSnapshot, snapshot: LayoutElementRenderSnapshot,
/// Snapshot rendered into a texture (happens lazily).
snapshot_texture: OnceCell<Option<(GlesTexture, Rectangle<i32, Physical>)>>,
snapshot_blocked_out_texture: OnceCell<Option<(GlesTexture, Rectangle<i32, Physical>)>>,
} }
#[derive(Debug)] #[derive(Debug)]
@@ -167,8 +161,6 @@ impl<W: LayoutElement> Tile<W> {
anim, anim,
size_from, size_from,
snapshot: animate_from, snapshot: animate_from,
snapshot_texture: OnceCell::new(),
snapshot_blocked_out_texture: OnceCell::new(),
}); });
} else { } else {
self.resize_animation = None; self.resize_animation = None;
@@ -499,7 +491,7 @@ impl<W: LayoutElement> Tile<W> {
if let Some(resize) = &self.resize_animation { if let Some(resize) = &self.resize_animation {
if Shaders::get(gles_renderer).crossfade.is_some() { if Shaders::get(gles_renderer).crossfade.is_some() {
if let Some(texture_from) = resize.rendered_texture(gles_renderer, scale, target) { if let Some(texture_from) = resize.snapshot.texture(gles_renderer, scale, target) {
let window_elements = let window_elements =
self.window self.window
.render(gles_renderer, Point::from((0, 0)), scale, 1., target); .render(gles_renderer, Point::from((0, 0)), scale, 1., target);
@@ -702,13 +694,10 @@ impl<W: LayoutElement> Tile<W> {
renderer: &mut GlesRenderer, renderer: &mut GlesRenderer,
scale: Scale<f64>, scale: Scale<f64>,
view_size: Size<i32, Logical>, view_size: Size<i32, Logical>,
) -> RenderSnapshot<TileSnapshotRenderElement, TileSnapshotRenderElement> { ) -> Option<RenderSnapshot<TileSnapshotRenderElement, TileSnapshotRenderElement>> {
let snapshot = self.window.take_last_render(); let snapshot = self.window.take_unmap_snapshot()?;
if snapshot.contents.is_empty() {
return RenderSnapshot::default();
}
RenderSnapshot { Some(RenderSnapshot {
contents: self.render_snapshot(renderer, scale, view_size, snapshot.contents), contents: self.render_snapshot(renderer, scale, view_size, snapshot.contents),
blocked_out_contents: self.render_snapshot( blocked_out_contents: self.render_snapshot(
renderer, renderer,
@@ -717,79 +706,9 @@ impl<W: LayoutElement> Tile<W> {
snapshot.blocked_out_contents, snapshot.blocked_out_contents,
), ),
block_out_from: snapshot.block_out_from, block_out_from: snapshot.block_out_from,
} size: snapshot.size,
} texture: Default::default(),
} blocked_out_texture: Default::default(),
})
impl ResizeAnimation {
fn rendered_texture(
&self,
renderer: &mut GlesRenderer,
scale: Scale<f64>,
target: RenderTarget,
) -> &Option<(GlesTexture, Rectangle<i32, Physical>)> {
let block_out = match self.snapshot.render.block_out_from {
None => false,
Some(BlockOutFrom::Screencast) => target == RenderTarget::Screencast,
Some(BlockOutFrom::ScreenCapture) => target != RenderTarget::Output,
};
if block_out {
self.snapshot_blocked_out_texture.get_or_init(|| {
let _span = tracy_client::span!("ResizeAnimation::rendered_texture");
let elements: Vec<_> = self
.snapshot
.render
.blocked_out_contents
.iter()
.map(|baked| {
baked.to_render_element(Point::from((0, 0)), scale, 1., Kind::Unspecified)
})
.collect();
match render_to_encompassing_texture(
renderer,
scale,
Transform::Normal,
Fourcc::Abgr8888,
&elements,
) {
Ok((texture, _sync_point, geo)) => Some((texture, geo)),
Err(err) => {
warn!("error rendering snapshot to texture: {err:?}");
None
}
}
})
} else {
self.snapshot_texture.get_or_init(|| {
let _span = tracy_client::span!("ResizeAnimation::rendered_texture");
let elements: Vec<_> = self
.snapshot
.render
.contents
.iter()
.map(|baked| {
baked.to_render_element(Point::from((0, 0)), scale, 1., Kind::Unspecified)
})
.collect();
match render_to_encompassing_texture(
renderer,
scale,
Transform::Normal,
Fourcc::Abgr8888,
&elements,
) {
Ok((texture, _sync_point, geo)) => Some((texture, geo)),
Err(err) => {
warn!("error rendering snapshot to texture: {err:?}");
None
}
}
})
}
} }
} }
+3 -2
View File
@@ -965,8 +965,9 @@ impl<W: LayoutElement> Workspace<W> {
.map(|o| Scale::from(o.current_scale().fractional_scale())) .map(|o| Scale::from(o.current_scale().fractional_scale()))
.unwrap_or(Scale::from(1.)); .unwrap_or(Scale::from(1.));
let snapshot = tile.take_snapshot_for_close_anim(renderer, output_scale, self.view_size); let Some(snapshot) =
if snapshot.contents.is_empty() { tile.take_snapshot_for_close_anim(renderer, output_scale, self.view_size)
else {
return; return;
}; };
+1 -24
View File
@@ -1,7 +1,6 @@
use std::ptr; use std::ptr;
use anyhow::{ensure, Context}; use anyhow::{ensure, Context};
use niri_config::BlockOutFrom;
use smithay::backend::allocator::Fourcc; use smithay::backend::allocator::Fourcc;
use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement}; use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement};
use smithay::backend::renderer::element::texture::{TextureBuffer, TextureRenderElement}; use smithay::backend::renderer::element::texture::{TextureBuffer, TextureRenderElement};
@@ -27,6 +26,7 @@ pub mod render_elements;
pub mod renderer; pub mod renderer;
pub mod resources; pub mod resources;
pub mod shaders; pub mod shaders;
pub mod snapshot;
pub mod surface; pub mod surface;
/// What we're rendering for. /// What we're rendering for.
@@ -49,19 +49,6 @@ pub struct BakedBuffer<B> {
pub dst: Option<Size<i32, Logical>>, pub dst: Option<Size<i32, Logical>>,
} }
/// Snapshot of a render.
#[derive(Debug)]
pub struct RenderSnapshot<C, B> {
/// Contents for a normal render.
pub contents: Vec<C>,
/// Blocked-out contents.
pub blocked_out_contents: Vec<B>,
/// Where the contents were blocked out from at the time of the snapshot.
pub block_out_from: Option<BlockOutFrom>,
}
pub trait ToRenderElement { pub trait ToRenderElement {
type RenderElement; type RenderElement;
@@ -118,16 +105,6 @@ impl ToRenderElement for BakedBuffer<SolidColorBuffer> {
} }
} }
impl<C, B> Default for RenderSnapshot<C, B> {
fn default() -> Self {
Self {
contents: Default::default(),
blocked_out_contents: Default::default(),
block_out_from: Default::default(),
}
}
}
pub fn render_to_encompassing_texture( pub fn render_to_encompassing_texture(
renderer: &mut GlesRenderer, renderer: &mut GlesRenderer,
scale: Scale<f64>, scale: Scale<f64>,
+111
View File
@@ -0,0 +1,111 @@
use std::cell::OnceCell;
use niri_config::BlockOutFrom;
use smithay::backend::allocator::Fourcc;
use smithay::backend::renderer::element::{Kind, RenderElement};
use smithay::backend::renderer::gles::{GlesRenderer, GlesTexture};
use smithay::utils::{Logical, Physical, Point, Rectangle, Scale, Size, Transform};
use super::{render_to_encompassing_texture, RenderTarget, ToRenderElement};
/// Snapshot of a render.
#[derive(Debug)]
pub struct RenderSnapshot<C, B> {
/// Contents for a normal render.
///
/// Relative to the geometry.
pub contents: Vec<C>,
/// Blocked-out contents.
///
/// Relative to the geometry.
pub blocked_out_contents: Vec<B>,
/// Where the contents were blocked out from at the time of the snapshot.
pub block_out_from: Option<BlockOutFrom>,
/// Visual size of the element at the point of the snapshot.
pub size: Size<i32, Logical>,
/// Contents rendered into a texture (lazily).
pub texture: OnceCell<Option<(GlesTexture, Rectangle<i32, Physical>)>>,
/// Blocked-out contents rendered into a texture (lazily).
pub blocked_out_texture: OnceCell<Option<(GlesTexture, Rectangle<i32, Physical>)>>,
}
impl<C, B, EC, EB> RenderSnapshot<C, B>
where
C: ToRenderElement<RenderElement = EC>,
B: ToRenderElement<RenderElement = EB>,
EC: RenderElement<GlesRenderer>,
EB: RenderElement<GlesRenderer>,
{
pub fn texture(
&self,
renderer: &mut GlesRenderer,
scale: Scale<f64>,
target: RenderTarget,
) -> Option<&(GlesTexture, Rectangle<i32, Physical>)> {
let block_out = match self.block_out_from {
None => false,
Some(BlockOutFrom::Screencast) => target == RenderTarget::Screencast,
Some(BlockOutFrom::ScreenCapture) => target != RenderTarget::Output,
};
if block_out {
self.blocked_out_texture.get_or_init(|| {
let _span = tracy_client::span!("RenderSnapshot::Texture");
let elements: Vec<_> = self
.blocked_out_contents
.iter()
.map(|baked| {
baked.to_render_element(Point::from((0, 0)), scale, 1., Kind::Unspecified)
})
.collect();
match render_to_encompassing_texture(
renderer,
scale,
Transform::Normal,
Fourcc::Abgr8888,
&elements,
) {
Ok((texture, _sync_point, geo)) => Some((texture, geo)),
Err(err) => {
warn!("error rendering blocked-out contents to texture: {err:?}");
None
}
}
})
} else {
self.texture.get_or_init(|| {
let _span = tracy_client::span!("RenderSnapshot::Texture");
let elements: Vec<_> = self
.contents
.iter()
.map(|baked| {
baked.to_render_element(Point::from((0, 0)), scale, 1., Kind::Unspecified)
})
.collect();
match render_to_encompassing_texture(
renderer,
scale,
Transform::Normal,
Fourcc::Abgr8888,
&elements,
) {
Ok((texture, _sync_point, geo)) => Some((texture, geo)),
Err(err) => {
warn!("error rendering contents to texture: {err:?}");
None
}
}
})
}
.as_ref()
}
}
+32 -30
View File
@@ -18,13 +18,12 @@ use smithay::wayland::compositor::{
use smithay::wayland::shell::xdg::{SurfaceCachedState, ToplevelSurface}; use smithay::wayland::shell::xdg::{SurfaceCachedState, ToplevelSurface};
use super::{ResolvedWindowRules, WindowRef}; use super::{ResolvedWindowRules, WindowRef};
use crate::layout::{ use crate::layout::{LayoutElement, LayoutElementRenderElement, LayoutElementRenderSnapshot};
AnimationSnapshot, LayoutElement, LayoutElementRenderElement, LayoutElementRenderSnapshot,
};
use crate::niri::WindowOffscreenId; use crate::niri::WindowOffscreenId;
use crate::render_helpers::renderer::NiriRenderer; use crate::render_helpers::renderer::NiriRenderer;
use crate::render_helpers::snapshot::RenderSnapshot;
use crate::render_helpers::surface::render_snapshot_from_surface_tree; use crate::render_helpers::surface::render_snapshot_from_surface_tree;
use crate::render_helpers::{BakedBuffer, RenderSnapshot, RenderTarget}; use crate::render_helpers::{BakedBuffer, RenderTarget};
#[derive(Debug)] #[derive(Debug)]
pub struct Mapped { pub struct Mapped {
@@ -49,7 +48,7 @@ pub struct Mapped {
block_out_buffer: RefCell<SolidColorBuffer>, block_out_buffer: RefCell<SolidColorBuffer>,
/// Snapshot of the last render for use in the close animation. /// Snapshot of the last render for use in the close animation.
last_render: RefCell<LayoutElementRenderSnapshot>, unmap_snapshot: RefCell<Option<LayoutElementRenderSnapshot>>,
/// Whether the next configure should be animated, if the configured state changed. /// Whether the next configure should be animated, if the configured state changed.
animate_next_configure: bool, animate_next_configure: bool,
@@ -58,7 +57,7 @@ pub struct Mapped {
animate_serials: Vec<Serial>, animate_serials: Vec<Serial>,
/// Snapshot right before an animated commit. /// Snapshot right before an animated commit.
animation_snapshot: Option<AnimationSnapshot>, animation_snapshot: Option<LayoutElementRenderSnapshot>,
} }
impl Mapped { impl Mapped {
@@ -70,7 +69,7 @@ impl Mapped {
need_to_recompute_rules: false, need_to_recompute_rules: false,
is_focused: false, is_focused: false,
block_out_buffer: RefCell::new(SolidColorBuffer::new((0, 0), [0., 0., 0., 1.])), block_out_buffer: RefCell::new(SolidColorBuffer::new((0, 0), [0., 0., 0., 1.])),
last_render: RefCell::new(RenderSnapshot::default()), unmap_snapshot: RefCell::new(None),
animate_next_configure: false, animate_next_configure: false,
animate_serials: Vec::new(), animate_serials: Vec::new(),
animation_snapshot: None, animation_snapshot: None,
@@ -118,14 +117,11 @@ impl Mapped {
fn render_snapshot(&self, renderer: &mut GlesRenderer) -> LayoutElementRenderSnapshot { fn render_snapshot(&self, renderer: &mut GlesRenderer) -> LayoutElementRenderSnapshot {
let _span = tracy_client::span!("Mapped::render_snapshot"); let _span = tracy_client::span!("Mapped::render_snapshot");
let mut snapshot = RenderSnapshot { let size = self.size();
block_out_from: self.rules.block_out_from,
..Default::default()
};
let mut buffer = self.block_out_buffer.borrow_mut(); let mut buffer = self.block_out_buffer.borrow_mut();
buffer.resize(self.window.geometry().size); buffer.resize(size);
snapshot.blocked_out_contents = vec![BakedBuffer { let blocked_out_contents = vec![BakedBuffer {
buffer: buffer.clone(), buffer: buffer.clone(),
location: Point::from((0, 0)), location: Point::from((0, 0)),
src: None, src: None,
@@ -134,6 +130,8 @@ impl Mapped {
let buf_pos = self.window.geometry().loc.upscale(-1); let buf_pos = self.window.geometry().loc.upscale(-1);
let mut contents = vec![];
let surface = self.toplevel().wl_surface(); let surface = self.toplevel().wl_surface();
for (popup, popup_offset) in PopupManager::popups_for_surface(surface) { for (popup, popup_offset) in PopupManager::popups_for_surface(surface) {
let offset = self.window.geometry().loc + popup_offset - popup.geometry().loc; let offset = self.window.geometry().loc + popup_offset - popup.geometry().loc;
@@ -142,22 +140,29 @@ impl Mapped {
renderer, renderer,
popup.wl_surface(), popup.wl_surface(),
buf_pos + offset, buf_pos + offset,
&mut snapshot.contents, &mut contents,
); );
} }
render_snapshot_from_surface_tree(renderer, surface, buf_pos, &mut snapshot.contents); render_snapshot_from_surface_tree(renderer, surface, buf_pos, &mut contents);
snapshot RenderSnapshot {
contents,
blocked_out_contents,
block_out_from: self.rules().block_out_from,
size,
texture: Default::default(),
blocked_out_texture: Default::default(),
}
} }
pub fn render_and_store_snapshot(&self, renderer: &mut GlesRenderer) { pub fn store_unmap_snapshot_if_empty(&self, renderer: &mut GlesRenderer) {
let mut snapshot = self.last_render.borrow_mut(); let mut snapshot = self.unmap_snapshot.borrow_mut();
if !snapshot.contents.is_empty() { if snapshot.is_some() {
return; return;
} }
*snapshot = self.render_snapshot(renderer); *snapshot = Some(self.render_snapshot(renderer));
} }
pub fn should_animate_commit(&mut self, commit_serial: Serial) -> bool { pub fn should_animate_commit(&mut self, commit_serial: Serial) -> bool {
@@ -174,10 +179,7 @@ impl Mapped {
} }
pub fn store_animation_snapshot(&mut self, renderer: &mut GlesRenderer) { pub fn store_animation_snapshot(&mut self, renderer: &mut GlesRenderer) {
self.animation_snapshot = Some(AnimationSnapshot { self.animation_snapshot = Some(self.render_snapshot(renderer));
render: self.render_snapshot(renderer),
size: self.size(),
});
} }
} }
@@ -239,10 +241,6 @@ impl LayoutElement for Mapped {
} }
} }
fn take_last_render(&self) -> LayoutElementRenderSnapshot {
self.last_render.take()
}
fn request_size(&mut self, size: Size<i32, Logical>, animate: bool) { fn request_size(&mut self, size: Size<i32, Logical>, animate: bool) {
let changed = self.toplevel().with_pending_state(|state| { let changed = self.toplevel().with_pending_state(|state| {
let changed = state.size != Some(size); let changed = state.size != Some(size);
@@ -382,11 +380,15 @@ impl LayoutElement for Mapped {
&self.rules &self.rules
} }
fn animation_snapshot(&self) -> Option<&AnimationSnapshot> { fn take_unmap_snapshot(&self) -> Option<LayoutElementRenderSnapshot> {
self.unmap_snapshot.take()
}
fn animation_snapshot(&self) -> Option<&LayoutElementRenderSnapshot> {
self.animation_snapshot.as_ref() self.animation_snapshot.as_ref()
} }
fn take_animation_snapshot(&mut self) -> Option<AnimationSnapshot> { fn take_animation_snapshot(&mut self) -> Option<LayoutElementRenderSnapshot> {
self.animation_snapshot.take() self.animation_snapshot.take()
} }
} }