mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-23 02:05:33 +07:00
Implement custom shader for window-close anim
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Context as _;
|
||||
use glam::{Mat3, Vec2};
|
||||
use niri_config::BlockOutFrom;
|
||||
use smithay::backend::allocator::Fourcc;
|
||||
use smithay::backend::renderer::element::texture::TextureRenderElement;
|
||||
@@ -8,13 +10,15 @@ use smithay::backend::renderer::element::utils::{
|
||||
Relocate, RelocateRenderElement, RescaleRenderElement,
|
||||
};
|
||||
use smithay::backend::renderer::element::{Id, Kind, RenderElement};
|
||||
use smithay::backend::renderer::gles::{GlesRenderer, GlesTexture};
|
||||
use smithay::backend::renderer::Renderer as _;
|
||||
use smithay::backend::renderer::gles::{GlesRenderer, GlesTexture, Uniform};
|
||||
use smithay::backend::renderer::{Renderer as _, Texture};
|
||||
use smithay::utils::{Logical, Point, Rectangle, Scale, Size, Transform};
|
||||
|
||||
use crate::animation::Animation;
|
||||
use crate::niri_render_elements;
|
||||
use crate::render_helpers::primary_gpu_texture::PrimaryGpuTextureRenderElement;
|
||||
use crate::render_helpers::shader_element::ShaderRenderElement;
|
||||
use crate::render_helpers::shaders::{mat3_uniform, ProgramType, Shaders};
|
||||
use crate::render_helpers::snapshot::RenderSnapshot;
|
||||
use crate::render_helpers::{render_to_encompassing_texture, RenderTarget};
|
||||
|
||||
@@ -49,11 +53,15 @@ pub struct ClosingWindow {
|
||||
|
||||
/// The closing animation.
|
||||
anim: Animation,
|
||||
|
||||
/// Random seed for the shader.
|
||||
random_seed: f32,
|
||||
}
|
||||
|
||||
niri_render_elements! {
|
||||
ClosingWindowRenderElement => {
|
||||
Texture = RelocateRenderElement<RescaleRenderElement<PrimaryGpuTextureRenderElement>>,
|
||||
Shader = ShaderRenderElement,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +108,7 @@ impl ClosingWindow {
|
||||
texture_offset,
|
||||
blocked_out_texture_offset,
|
||||
anim,
|
||||
random_seed: fastrand::f32(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -108,16 +117,18 @@ impl ClosingWindow {
|
||||
}
|
||||
|
||||
pub fn are_animations_ongoing(&self) -> bool {
|
||||
!self.anim.is_clamped_done()
|
||||
!self.anim.is_done()
|
||||
}
|
||||
|
||||
pub fn render(
|
||||
&self,
|
||||
renderer: &mut GlesRenderer,
|
||||
view_rect: Rectangle<i32, Logical>,
|
||||
scale: Scale<f64>,
|
||||
target: RenderTarget,
|
||||
) -> ClosingWindowRenderElement {
|
||||
let val = self.anim.clamped_value();
|
||||
let progress = self.anim.value();
|
||||
let clamped_progress = self.anim.clamped_value().clamp(0., 1.);
|
||||
|
||||
let (texture, offset) = if target.should_block_out(self.block_out_from) {
|
||||
(&self.blocked_out_texture, self.blocked_out_texture_offset)
|
||||
@@ -125,6 +136,43 @@ impl ClosingWindow {
|
||||
(&self.texture, self.texture_offset)
|
||||
};
|
||||
|
||||
if Shaders::get(renderer).program(ProgramType::Close).is_some() {
|
||||
let area_loc = Vec2::new(view_rect.loc.x as f32, view_rect.loc.y as f32);
|
||||
let area_size = Vec2::new(view_rect.size.w as f32, view_rect.size.h as f32);
|
||||
|
||||
let geo_loc = Vec2::new(self.pos.x as f32, self.pos.y as f32);
|
||||
let geo_size = Vec2::new(self.geo_size.w as f32, self.geo_size.h as f32);
|
||||
|
||||
let input_to_geo = Mat3::from_scale(area_size / geo_size)
|
||||
* Mat3::from_translation((area_loc - geo_loc) / area_size);
|
||||
|
||||
let tex_scale = Vec2::new(self.texture_scale.x as f32, self.texture_scale.y as f32);
|
||||
let tex_loc = Vec2::new(offset.x as f32, offset.y as f32);
|
||||
let tex_size = Vec2::new(texture.width() as f32, texture.height() as f32) / tex_scale;
|
||||
|
||||
let geo_to_tex =
|
||||
Mat3::from_translation(-tex_loc / tex_size) * Mat3::from_scale(geo_size / tex_size);
|
||||
|
||||
return ShaderRenderElement::new(
|
||||
ProgramType::Close,
|
||||
view_rect.size,
|
||||
None,
|
||||
1.,
|
||||
vec![
|
||||
mat3_uniform("niri_input_to_geo", input_to_geo),
|
||||
Uniform::new("niri_geo_size", geo_size.to_array()),
|
||||
mat3_uniform("niri_geo_to_tex", geo_to_tex),
|
||||
Uniform::new("niri_progress", progress as f32),
|
||||
Uniform::new("niri_clamped_progress", clamped_progress as f32),
|
||||
Uniform::new("niri_random_seed", self.random_seed),
|
||||
],
|
||||
HashMap::from([(String::from("niri_tex"), texture.clone())]),
|
||||
Kind::Unspecified,
|
||||
)
|
||||
.with_location(Point::from((0, 0)))
|
||||
.into();
|
||||
}
|
||||
|
||||
let elem = TextureRenderElement::from_static_texture(
|
||||
Id::new(),
|
||||
self.texture_renderer_id,
|
||||
@@ -132,7 +180,7 @@ impl ClosingWindow {
|
||||
texture.clone(),
|
||||
self.texture_scale.x as i32,
|
||||
Transform::Normal,
|
||||
Some(val.clamp(0., 1.) as f32),
|
||||
Some(1. - clamped_progress as f32),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
@@ -145,7 +193,7 @@ impl ClosingWindow {
|
||||
let elem = RescaleRenderElement::from_element(
|
||||
elem,
|
||||
(center - offset).to_physical_precise_round(scale),
|
||||
(val / 5. + 0.8).max(0.),
|
||||
((1. - clamped_progress) / 5. + 0.8).max(0.),
|
||||
);
|
||||
|
||||
let mut location = self.pos.to_f64() + offset;
|
||||
|
||||
Reference in New Issue
Block a user