diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-04-13 14:16:07 +0400 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-04-13 14:16:07 +0400 |
| commit | 9d5f1c7ef7e1b038fe6242aaa04009bf21463d2a (patch) | |
| tree | c766cd95b619175ba748ca7d804a19adf505d70f /src/render_helpers/snapshot.rs | |
| parent | 71be19b234d58f4ec447e921633506beb81a52c0 (diff) | |
| download | niri-9d5f1c7ef7e1b038fe6242aaa04009bf21463d2a.tar.gz niri-9d5f1c7ef7e1b038fe6242aaa04009bf21463d2a.tar.bz2 niri-9d5f1c7ef7e1b038fe6242aaa04009bf21463d2a.zip | |
Unify Animation- and RenderSnapshot
Diffstat (limited to 'src/render_helpers/snapshot.rs')
| -rw-r--r-- | src/render_helpers/snapshot.rs | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/src/render_helpers/snapshot.rs b/src/render_helpers/snapshot.rs new file mode 100644 index 00000000..b394dcd9 --- /dev/null +++ b/src/render_helpers/snapshot.rs @@ -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() + } +} |
