diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2025-11-16 11:26:40 +0300 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2025-11-16 22:36:01 +0300 |
| commit | b774fc1bafd3f9c612ad117986510f8710fd7cc6 (patch) | |
| tree | 5c849941e364c48f49708f722649e3c610e92eac /src/render_helpers/gradient_fade_texture.rs | |
| parent | 661fcd42ad284bf4cf68581ae0979fe04b0f2838 (diff) | |
| download | niri-b774fc1bafd3f9c612ad117986510f8710fd7cc6.tar.gz niri-b774fc1bafd3f9c612ad117986510f8710fd7cc6.tar.bz2 niri-b774fc1bafd3f9c612ad117986510f8710fd7cc6.zip | |
render_helpers: Add GradientFadeTexture
Diffstat (limited to 'src/render_helpers/gradient_fade_texture.rs')
| -rw-r--r-- | src/render_helpers/gradient_fade_texture.rs | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/src/render_helpers/gradient_fade_texture.rs b/src/render_helpers/gradient_fade_texture.rs new file mode 100644 index 00000000..a51ded33 --- /dev/null +++ b/src/render_helpers/gradient_fade_texture.rs @@ -0,0 +1,136 @@ +use smithay::backend::renderer::element::{Element, Id, Kind, RenderElement, UnderlyingStorage}; +use smithay::backend::renderer::gles::{ + GlesError, GlesFrame, GlesRenderer, GlesTexProgram, GlesTexture, Uniform, +}; +use smithay::backend::renderer::utils::{CommitCounter, DamageSet, OpaqueRegions}; +use smithay::utils::{Buffer, Physical, Rectangle, Scale, Transform}; + +use super::texture::TextureRenderElement; +use crate::backend::tty::{TtyFrame, TtyRenderer, TtyRendererError}; +use crate::render_helpers::renderer::AsGlesFrame as _; +use crate::render_helpers::shaders::Shaders; + +#[derive(Debug, Clone)] +pub struct GradientFadeTextureRenderElement { + inner: TextureRenderElement<GlesTexture>, + program: GradientFadeShader, + uniforms: Vec<Uniform<'static>>, +} + +#[derive(Debug, Clone)] +pub struct GradientFadeShader(GlesTexProgram); + +impl GradientFadeTextureRenderElement { + pub fn new(texture: TextureRenderElement<GlesTexture>, program: GradientFadeShader) -> Self { + let logical_w = texture.buffer().logical_size().w; + let logical_src_w = texture.logical_src().size.w; + let cutoff = if logical_src_w < logical_w { + // Texture is clipped, add a fade. + let cutoff = 1. - f64::min(18. / logical_src_w, 1.); + let full = logical_src_w / logical_w; + ((cutoff * full) as f32, full as f32) + } else { + // Texture is displayed full-size, no cutoff necessary. + (1., 1.) + }; + let uniforms = vec![Uniform::new("cutoff", cutoff)]; + Self { + inner: texture, + program, + uniforms, + } + } + + pub fn shader(renderer: &mut GlesRenderer) -> Option<GradientFadeShader> { + let program = Shaders::get(renderer).gradient_fade.clone(); + program.map(GradientFadeShader) + } +} + +impl Element for GradientFadeTextureRenderElement { + fn id(&self) -> &Id { + self.inner.id() + } + + fn current_commit(&self) -> CommitCounter { + self.inner.current_commit() + } + + fn geometry(&self, scale: Scale<f64>) -> Rectangle<i32, Physical> { + self.inner.geometry(scale) + } + + fn transform(&self) -> Transform { + self.inner.transform() + } + + fn src(&self) -> Rectangle<f64, Buffer> { + self.inner.src() + } + + fn damage_since( + &self, + scale: Scale<f64>, + commit: Option<CommitCounter>, + ) -> DamageSet<i32, Physical> { + self.inner.damage_since(scale, commit) + } + + fn opaque_regions(&self, scale: Scale<f64>) -> OpaqueRegions<i32, Physical> { + self.inner.opaque_regions(scale) + } + + fn alpha(&self) -> f32 { + self.inner.alpha() + } + + fn kind(&self) -> Kind { + self.inner.kind() + } +} + +impl RenderElement<GlesRenderer> for GradientFadeTextureRenderElement { + fn draw( + &self, + frame: &mut GlesFrame<'_, '_>, + src: Rectangle<f64, Buffer>, + dst: Rectangle<i32, Physical>, + damage: &[Rectangle<i32, Physical>], + opaque_regions: &[Rectangle<i32, Physical>], + ) -> Result<(), GlesError> { + frame.override_default_tex_program(self.program.0.clone(), self.uniforms.clone()); + RenderElement::<GlesRenderer>::draw(&self.inner, frame, src, dst, damage, opaque_regions)?; + frame.clear_tex_program_override(); + Ok(()) + } + + fn underlying_storage(&self, _renderer: &mut GlesRenderer) -> Option<UnderlyingStorage<'_>> { + // If scanout for things other than Wayland buffers is implemented, this will need to take + // the target GPU into account. + None + } +} + +impl<'render> RenderElement<TtyRenderer<'render>> for GradientFadeTextureRenderElement { + fn draw( + &self, + frame: &mut TtyFrame<'render, '_, '_>, + src: Rectangle<f64, Buffer>, + dst: Rectangle<i32, Physical>, + damage: &[Rectangle<i32, Physical>], + opaque_regions: &[Rectangle<i32, Physical>], + ) -> Result<(), TtyRendererError<'render>> { + let gles_frame = frame.as_gles_frame(); + RenderElement::<GlesRenderer>::draw(&self, gles_frame, src, dst, damage, opaque_regions)?; + Ok(()) + } + + fn underlying_storage( + &self, + _renderer: &mut TtyRenderer<'render>, + ) -> Option<UnderlyingStorage<'_>> { + // If scanout for things other than Wayland buffers is implemented, this will need to take + // the target GPU into account. + None + } +} |
