mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-24 02:01:18 +07:00
render_helpers: Add GradientFadeTexture
This commit is contained in:
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ pub mod border;
|
|||||||
pub mod clipped_surface;
|
pub mod clipped_surface;
|
||||||
pub mod damage;
|
pub mod damage;
|
||||||
pub mod debug;
|
pub mod debug;
|
||||||
|
pub mod gradient_fade_texture;
|
||||||
pub mod memory;
|
pub mod memory;
|
||||||
pub mod offscreen;
|
pub mod offscreen;
|
||||||
pub mod primary_gpu_texture;
|
pub mod primary_gpu_texture;
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
#version 100
|
||||||
|
|
||||||
|
//_DEFINES_
|
||||||
|
|
||||||
|
#if defined(EXTERNAL)
|
||||||
|
#extension GL_OES_EGL_image_external : require
|
||||||
|
#endif
|
||||||
|
|
||||||
|
precision highp float;
|
||||||
|
#if defined(EXTERNAL)
|
||||||
|
uniform samplerExternalOES tex;
|
||||||
|
#else
|
||||||
|
uniform sampler2D tex;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uniform float alpha;
|
||||||
|
varying vec2 v_coords;
|
||||||
|
|
||||||
|
#if defined(DEBUG_FLAGS)
|
||||||
|
uniform float tint;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// x is left edge, y is right edge of the gradient.
|
||||||
|
uniform vec2 cutoff;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
// Sample the texture.
|
||||||
|
vec4 color = texture2D(tex, v_coords);
|
||||||
|
#if defined(NO_ALPHA)
|
||||||
|
color = vec4(color.rgb, 1.0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (cutoff.x < cutoff.y) {
|
||||||
|
float fade = clamp((cutoff.y - v_coords.x) / (cutoff.y - cutoff.x), 0.0, 1.0);
|
||||||
|
color = color * fade;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply final alpha and tint.
|
||||||
|
color = color * alpha;
|
||||||
|
|
||||||
|
#if defined(DEBUG_FLAGS)
|
||||||
|
if (tint == 1.0)
|
||||||
|
color = vec4(0.0, 0.2, 0.0, 0.2) + color * 0.8;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gl_FragColor = color;
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@ pub struct Shaders {
|
|||||||
pub shadow: Option<ShaderProgram>,
|
pub shadow: Option<ShaderProgram>,
|
||||||
pub clipped_surface: Option<GlesTexProgram>,
|
pub clipped_surface: Option<GlesTexProgram>,
|
||||||
pub resize: Option<ShaderProgram>,
|
pub resize: Option<ShaderProgram>,
|
||||||
|
pub gradient_fade: Option<GlesTexProgram>,
|
||||||
pub custom_resize: RefCell<Option<ShaderProgram>>,
|
pub custom_resize: RefCell<Option<ShaderProgram>>,
|
||||||
pub custom_close: RefCell<Option<ShaderProgram>>,
|
pub custom_close: RefCell<Option<ShaderProgram>>,
|
||||||
pub custom_open: RefCell<Option<ShaderProgram>>,
|
pub custom_open: RefCell<Option<ShaderProgram>>,
|
||||||
@@ -96,11 +97,22 @@ impl Shaders {
|
|||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
|
let gradient_fade = renderer
|
||||||
|
.compile_custom_texture_shader(
|
||||||
|
include_str!("gradient_fade.frag"),
|
||||||
|
&[UniformName::new("cutoff", UniformType::_2f)],
|
||||||
|
)
|
||||||
|
.map_err(|err| {
|
||||||
|
warn!("error compiling gradient fade shader: {err:?}");
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
border,
|
border,
|
||||||
shadow,
|
shadow,
|
||||||
clipped_surface,
|
clipped_surface,
|
||||||
resize,
|
resize,
|
||||||
|
gradient_fade,
|
||||||
custom_resize: RefCell::new(None),
|
custom_resize: RefCell::new(None),
|
||||||
custom_close: RefCell::new(None),
|
custom_close: RefCell::new(None),
|
||||||
custom_open: RefCell::new(None),
|
custom_open: RefCell::new(None),
|
||||||
|
|||||||
@@ -152,6 +152,11 @@ impl<T: Texture> TextureRenderElement<T> {
|
|||||||
.or_else(|| self.src.map(|src| src.size))
|
.or_else(|| self.src.map(|src| src.size))
|
||||||
.unwrap_or_else(|| self.buffer.logical_size())
|
.unwrap_or_else(|| self.buffer.logical_size())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn logical_src(&self) -> Rectangle<f64, Logical> {
|
||||||
|
self.src
|
||||||
|
.unwrap_or_else(|| Rectangle::from_size(self.logical_size()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Texture> Element for TextureRenderElement<T> {
|
impl<T: Texture> Element for TextureRenderElement<T> {
|
||||||
|
|||||||
Reference in New Issue
Block a user