aboutsummaryrefslogtreecommitdiff
path: root/src/render_helpers/gradient_fade_texture.rs
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2025-11-16 11:26:40 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2025-11-16 22:36:01 +0300
commitb774fc1bafd3f9c612ad117986510f8710fd7cc6 (patch)
tree5c849941e364c48f49708f722649e3c610e92eac /src/render_helpers/gradient_fade_texture.rs
parent661fcd42ad284bf4cf68581ae0979fe04b0f2838 (diff)
downloadniri-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.rs136
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
+ }
+}