forked from Mirror/niri
feat(blur,clipped_surface): move responsibility for masking content alpha out of blur
Closes #3
This commit is contained in:
@@ -16,7 +16,9 @@ use crate::layout::shadow::Shadow;
|
||||
use crate::niri_render_elements;
|
||||
use crate::render_helpers::blur::element::BlurRenderElement;
|
||||
use crate::render_helpers::blur::EffectsFramebufffersUserData;
|
||||
use crate::render_helpers::clipped_surface::ClippedSurfaceRenderElement;
|
||||
use crate::render_helpers::renderer::NiriRenderer;
|
||||
use crate::render_helpers::shaders::Shaders;
|
||||
use crate::render_helpers::shadow::ShadowRenderElement;
|
||||
use crate::render_helpers::solid_color::{SolidColorBuffer, SolidColorRenderElement};
|
||||
use crate::render_helpers::{render_to_texture, RenderTarget, SplitElements};
|
||||
@@ -59,6 +61,7 @@ niri_render_elements! {
|
||||
SolidColor = SolidColorRenderElement,
|
||||
Shadow = ShadowRenderElement,
|
||||
Blur = BlurRenderElement,
|
||||
ClippedBlur = ClippedSurfaceRenderElement<BlurRenderElement>,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,6 +198,7 @@ impl MappedLayer {
|
||||
let location = location + self.bob_offset();
|
||||
|
||||
let mut gles_elems: Option<Vec<LayerSurfaceRenderElement<GlesRenderer>>> = None;
|
||||
let ignore_alpha = self.rules.blur.ignore_alpha.unwrap_or_default().0;
|
||||
|
||||
if target.should_block_out(self.rules.block_out_from) {
|
||||
// Round to physical pixels.
|
||||
@@ -236,14 +240,16 @@ impl MappedLayer {
|
||||
Kind::ScanoutCandidate,
|
||||
);
|
||||
|
||||
gles_elems = Some(render_elements_from_surface_tree(
|
||||
renderer.as_gles_renderer(),
|
||||
surface,
|
||||
buf_pos.to_physical_precise_round(scale),
|
||||
scale,
|
||||
alpha,
|
||||
Kind::ScanoutCandidate,
|
||||
));
|
||||
gles_elems = (ignore_alpha > 0.).then(|| {
|
||||
render_elements_from_surface_tree(
|
||||
renderer.as_gles_renderer(),
|
||||
surface,
|
||||
buf_pos.to_physical_precise_round(scale),
|
||||
scale,
|
||||
alpha,
|
||||
Kind::ScanoutCandidate,
|
||||
)
|
||||
});
|
||||
};
|
||||
|
||||
let blur_elem = (self.blur_config.on
|
||||
@@ -253,39 +259,77 @@ impl MappedLayer {
|
||||
let fx_buffers = fx_buffers.borrow();
|
||||
|
||||
// TODO: respect sync point?
|
||||
let alpha_tex = gles_elems
|
||||
.and_then(|gles_elems| {
|
||||
let transform = fx_buffers.transform();
|
||||
let alpha_tex = (ignore_alpha > 0.)
|
||||
.then(|| {
|
||||
gles_elems.and_then(|gles_elems| {
|
||||
let transform = fx_buffers.transform();
|
||||
|
||||
render_to_texture(
|
||||
renderer.as_gles_renderer(),
|
||||
transform.transform_size(fx_buffers.output_size()),
|
||||
self.scale.into(),
|
||||
Transform::Normal,
|
||||
Fourcc::Abgr8888,
|
||||
gles_elems.into_iter(),
|
||||
)
|
||||
.inspect_err(|e| warn!("failed to render alpha tex: {e:?}"))
|
||||
.ok()
|
||||
render_to_texture(
|
||||
renderer.as_gles_renderer(),
|
||||
transform.transform_size(fx_buffers.output_size()),
|
||||
self.scale.into(),
|
||||
Transform::Normal,
|
||||
Fourcc::Abgr8888,
|
||||
gles_elems.into_iter(),
|
||||
)
|
||||
.inspect_err(|e| warn!("failed to render alpha tex: {e:?}"))
|
||||
.ok()
|
||||
})
|
||||
})
|
||||
.flatten()
|
||||
.map(|r| r.0);
|
||||
|
||||
Some(
|
||||
BlurRenderElement::new_optimized(
|
||||
renderer,
|
||||
&fx_buffers,
|
||||
Rectangle::new(location, self.size).to_i32_round(),
|
||||
location.to_physical_precise_round(self.scale),
|
||||
self.rules
|
||||
.geometry_corner_radius
|
||||
.unwrap_or_default()
|
||||
.top_left,
|
||||
self.scale,
|
||||
self.blur_config,
|
||||
let radius = self.rules.geometry_corner_radius.unwrap_or_default();
|
||||
|
||||
let blur_sample_area = Rectangle::new(location, self.size).to_i32_round();
|
||||
|
||||
let elem = BlurRenderElement::new_optimized(
|
||||
renderer,
|
||||
&fx_buffers,
|
||||
blur_sample_area,
|
||||
location.to_physical_precise_round(self.scale),
|
||||
self.rules
|
||||
.geometry_corner_radius
|
||||
.unwrap_or_default()
|
||||
.top_left,
|
||||
self.scale,
|
||||
self.blur_config,
|
||||
);
|
||||
|
||||
let geo = Rectangle::new(location, blur_sample_area.size.to_f64());
|
||||
|
||||
let clip_to_geometry =
|
||||
ClippedSurfaceRenderElement::will_clip(&elem, scale, geo, radius);
|
||||
|
||||
let clip_shader = (alpha_tex.is_some() || clip_to_geometry)
|
||||
.then(|| Shaders::get(renderer).clipped_surface.clone())
|
||||
.flatten();
|
||||
|
||||
let elem = if let Some(clip_shader) = clip_shader {
|
||||
let view_src = blur_sample_area.to_f64();
|
||||
let buf_size = fx_buffers
|
||||
.output_size()
|
||||
.to_f64()
|
||||
.to_logical(self.scale)
|
||||
.to_i32_round();
|
||||
|
||||
ClippedSurfaceRenderElement::new(
|
||||
elem,
|
||||
view_src,
|
||||
buf_size,
|
||||
self.scale.into(),
|
||||
geo,
|
||||
clip_shader,
|
||||
radius,
|
||||
alpha_tex,
|
||||
ignore_alpha,
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.into()
|
||||
} else {
|
||||
elem.into()
|
||||
};
|
||||
|
||||
Some(elem)
|
||||
})
|
||||
.flatten()
|
||||
.into_iter();
|
||||
|
||||
@@ -428,7 +428,8 @@ niri_render_elements! {
|
||||
Border = BorderRenderElement,
|
||||
Shadow = ShadowRenderElement,
|
||||
Blur = BlurRenderElement,
|
||||
ClippedSurface = ClippedSurfaceRenderElement<WaylandSurfaceRenderElement<R>, R>,
|
||||
BlurClippedSurface = ClippedSurfaceRenderElement<BlurRenderElement>,
|
||||
ClippedSurface = ClippedSurfaceRenderElement<WaylandSurfaceRenderElement<R>>,
|
||||
Offscreen = OffscreenRenderElement,
|
||||
ExtraDamage = ExtraDamage,
|
||||
TabIndicator = TabIndicatorRenderElement,
|
||||
@@ -1766,6 +1767,10 @@ impl<W: LayoutElement> Tile<W> {
|
||||
let mut window_popups = None;
|
||||
let mut rounded_corner_damage = None;
|
||||
let has_border_shader = BorderRenderElement::has_shader(renderer);
|
||||
let geo = Rectangle::new(window_render_loc, window_size);
|
||||
let clip_shader = clip_to_geometry
|
||||
.then(|| Shaders::get(renderer).clipped_surface.clone())
|
||||
.flatten();
|
||||
if resize_shader.is_none() && resize_fallback.is_none() {
|
||||
let window = self.window.focused_window().render(
|
||||
renderer,
|
||||
@@ -1775,16 +1780,15 @@ impl<W: LayoutElement> Tile<W> {
|
||||
target,
|
||||
);
|
||||
|
||||
let geo = Rectangle::new(window_render_loc, window_size);
|
||||
let radius = radius.fit_to(window_size.w as f32, window_size.h as f32);
|
||||
|
||||
let clip_shader = Shaders::get(renderer).clipped_surface.clone();
|
||||
|
||||
if clip_to_geometry && clip_shader.is_some() {
|
||||
let damage = self.rounded_corner_damage.element();
|
||||
rounded_corner_damage = Some(damage.with_location(window_render_loc).into());
|
||||
}
|
||||
|
||||
let clip_shader = clip_shader.clone();
|
||||
|
||||
window_surface = Some(window.normal.into_iter().map(move |elem| match elem {
|
||||
LayoutElementRenderElement::Wayland(elem) => {
|
||||
// If we should clip to geometry, render a clipped window.
|
||||
@@ -1801,6 +1805,8 @@ impl<W: LayoutElement> Tile<W> {
|
||||
geo,
|
||||
shader.clone(),
|
||||
radius,
|
||||
None,
|
||||
0.,
|
||||
)
|
||||
.into();
|
||||
}
|
||||
@@ -1928,19 +1934,40 @@ impl<W: LayoutElement> Tile<W> {
|
||||
let fx_buffers = fx_buffers?;
|
||||
let fx_buffers = fx_buffers.borrow();
|
||||
|
||||
Some(
|
||||
BlurRenderElement::new_optimized(
|
||||
renderer,
|
||||
&fx_buffers,
|
||||
blur_sample_area.to_i32_round(),
|
||||
window_render_loc.to_physical(self.scale).to_i32_round(),
|
||||
radius.top_left,
|
||||
self.scale,
|
||||
self.blur_config,
|
||||
let elem = BlurRenderElement::new_optimized(
|
||||
renderer,
|
||||
&fx_buffers,
|
||||
blur_sample_area.to_i32_round(),
|
||||
window_render_loc.to_physical(self.scale).to_i32_round(),
|
||||
radius.top_left,
|
||||
self.scale,
|
||||
self.blur_config,
|
||||
);
|
||||
|
||||
let elem = if clip_to_geometry {
|
||||
let view_src = blur_sample_area;
|
||||
let buf_size = fx_buffers
|
||||
.output_size()
|
||||
.to_f64()
|
||||
.to_logical(self.scale)
|
||||
.to_i32_round();
|
||||
ClippedSurfaceRenderElement::new(
|
||||
elem,
|
||||
view_src,
|
||||
buf_size,
|
||||
scale,
|
||||
geo,
|
||||
clip_shader?.clone(),
|
||||
radius,
|
||||
None,
|
||||
0.,
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.into()
|
||||
} else {
|
||||
elem.into()
|
||||
};
|
||||
|
||||
Some(elem)
|
||||
})
|
||||
.flatten()
|
||||
.into_iter();
|
||||
|
||||
@@ -81,7 +81,7 @@ use smithay::wayland::dmabuf::DmabufState;
|
||||
use smithay::wayland::fractional_scale::FractionalScaleManagerState;
|
||||
use smithay::wayland::idle_inhibit::IdleInhibitManagerState;
|
||||
use smithay::wayland::idle_notify::IdleNotifierState;
|
||||
use smithay::wayland::input_method::{InputMethodManagerState, InputMethodSeat};
|
||||
use smithay::wayland::input_method::InputMethodManagerState;
|
||||
use smithay::wayland::keyboard_shortcuts_inhibit::{
|
||||
KeyboardShortcutsInhibitState, KeyboardShortcutsInhibitor,
|
||||
};
|
||||
|
||||
@@ -4,9 +4,7 @@ use niri_config::Blur;
|
||||
|
||||
use smithay::backend::renderer::element::texture::TextureRenderElement;
|
||||
use smithay::backend::renderer::element::{Element, Id, Kind, RenderElement, UnderlyingStorage};
|
||||
use smithay::backend::renderer::gles::{
|
||||
ffi, GlesError, GlesFrame, GlesRenderer, GlesTexture, Uniform,
|
||||
};
|
||||
use smithay::backend::renderer::gles::{GlesError, GlesFrame, GlesRenderer, GlesTexture, Uniform};
|
||||
use smithay::backend::renderer::utils::{CommitCounter, DamageSet, OpaqueRegions};
|
||||
use smithay::backend::renderer::Renderer;
|
||||
use smithay::utils::{Buffer, Logical, Physical, Point, Rectangle, Scale, Size, Transform};
|
||||
@@ -34,7 +32,6 @@ pub enum BlurRenderElement {
|
||||
output_size: Size<i32, Physical>,
|
||||
config: Blur,
|
||||
output_transform: Transform,
|
||||
alpha_tex: Option<GlesTexture>,
|
||||
},
|
||||
/// Use true blur.
|
||||
///
|
||||
@@ -76,7 +73,6 @@ impl BlurRenderElement {
|
||||
corner_radius: f32,
|
||||
scale: f64,
|
||||
config: Blur,
|
||||
alpha_tex: Option<GlesTexture>,
|
||||
) -> Self {
|
||||
let texture = fx_buffers.optimized_blur.clone();
|
||||
|
||||
@@ -109,7 +105,6 @@ impl BlurRenderElement {
|
||||
scale,
|
||||
output_size: fx_buffers.output_size,
|
||||
output_transform: fx_buffers.transform,
|
||||
alpha_tex,
|
||||
config,
|
||||
}
|
||||
}
|
||||
@@ -342,16 +337,7 @@ impl RenderElement<GlesRenderer> for BlurRenderElement {
|
||||
let _span = trace_span!("blur_draw_gles").entered();
|
||||
|
||||
match self {
|
||||
Self::Optimized {
|
||||
tex,
|
||||
corner_radius,
|
||||
noise,
|
||||
scale,
|
||||
output_size,
|
||||
output_transform,
|
||||
config,
|
||||
alpha_tex,
|
||||
} => {
|
||||
Self::Optimized { tex, scale, .. } => {
|
||||
let downscaled_dst = Rectangle::new(
|
||||
dst.loc,
|
||||
Size::from((
|
||||
@@ -360,66 +346,14 @@ impl RenderElement<GlesRenderer> for BlurRenderElement {
|
||||
)),
|
||||
);
|
||||
|
||||
let program = Shaders::get_from_frame(gles_frame).blur_finish.clone();
|
||||
let gles_frame: &mut GlesFrame = gles_frame;
|
||||
let geo = output_transform.transform_rect_in(dst, output_size);
|
||||
gles_frame.override_default_tex_program(
|
||||
program.unwrap(),
|
||||
vec![
|
||||
Uniform::new(
|
||||
"geo",
|
||||
[
|
||||
geo.loc.x as f32,
|
||||
geo.loc.y as f32,
|
||||
geo.size.w as f32,
|
||||
geo.size.h as f32,
|
||||
],
|
||||
),
|
||||
Uniform::new("corner_radius", *corner_radius),
|
||||
Uniform::new("output_size", [output_size.w as f32, output_size.h as f32]),
|
||||
Uniform::new("noise", *noise),
|
||||
Uniform::new("alpha", self.alpha()),
|
||||
Uniform::new(
|
||||
"ignore_alpha",
|
||||
if alpha_tex.is_some() {
|
||||
config.ignore_alpha.0 as f32
|
||||
} else {
|
||||
0.
|
||||
},
|
||||
),
|
||||
Uniform::new("alpha_tex", 1),
|
||||
],
|
||||
);
|
||||
|
||||
if let Some(alpha_tex) = alpha_tex {
|
||||
gles_frame.with_context(|gl| unsafe {
|
||||
gl.ActiveTexture(ffi::TEXTURE1);
|
||||
gl.BindTexture(ffi::TEXTURE_2D, alpha_tex.tex_id());
|
||||
gl.TexParameteri(
|
||||
ffi::TEXTURE_2D,
|
||||
ffi::TEXTURE_MIN_FILTER,
|
||||
ffi::LINEAR as i32,
|
||||
);
|
||||
gl.TexParameteri(
|
||||
ffi::TEXTURE_2D,
|
||||
ffi::TEXTURE_MAG_FILTER,
|
||||
ffi::LINEAR as i32,
|
||||
);
|
||||
})?;
|
||||
}
|
||||
|
||||
let res = <TextureRenderElement<GlesTexture> as RenderElement<GlesRenderer>>::draw(
|
||||
<TextureRenderElement<GlesTexture> as RenderElement<GlesRenderer>>::draw(
|
||||
&tex.0,
|
||||
gles_frame,
|
||||
src,
|
||||
downscaled_dst,
|
||||
damage,
|
||||
opaque_regions,
|
||||
);
|
||||
|
||||
gles_frame.clear_tex_program_override();
|
||||
|
||||
res
|
||||
)
|
||||
}
|
||||
Self::TrueBlur {
|
||||
fx_buffers,
|
||||
|
||||
@@ -1,31 +1,28 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use glam::{Mat3, Vec2};
|
||||
use niri_config::CornerRadius;
|
||||
use smithay::backend::renderer::element::{Element, Id, Kind, RenderElement, UnderlyingStorage};
|
||||
use smithay::backend::renderer::gles::{
|
||||
GlesError, GlesFrame, GlesRenderer, GlesTexProgram, Uniform,
|
||||
ffi, GlesError, GlesFrame, GlesRenderer, GlesTexProgram, GlesTexture, Uniform,
|
||||
};
|
||||
use smithay::backend::renderer::utils::{CommitCounter, DamageSet, OpaqueRegions};
|
||||
use smithay::utils::{Buffer, Logical, Physical, Point, Rectangle, Scale, Size, Transform};
|
||||
|
||||
use super::damage::ExtraDamage;
|
||||
use super::renderer::{AsGlesFrame as _, NiriRenderer};
|
||||
use super::renderer::AsGlesFrame as _;
|
||||
use super::shaders::mat3_uniform;
|
||||
use crate::backend::tty::{TtyFrame, TtyRenderer, TtyRendererError};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ClippedSurfaceRenderElement<E, R>
|
||||
pub struct ClippedSurfaceRenderElement<E>
|
||||
where
|
||||
E: RenderElement<R>,
|
||||
R: NiriRenderer,
|
||||
E: Element,
|
||||
{
|
||||
inner: E,
|
||||
program: GlesTexProgram,
|
||||
corner_radius: CornerRadius,
|
||||
geometry: Rectangle<f64, Logical>,
|
||||
uniforms: Vec<Uniform<'static>>,
|
||||
marker: PhantomData<R>,
|
||||
alpha_tex: Option<GlesTexture>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
@@ -34,11 +31,11 @@ pub struct RoundedCornerDamage {
|
||||
corner_radius: CornerRadius,
|
||||
}
|
||||
|
||||
impl<E, R> ClippedSurfaceRenderElement<E, R>
|
||||
impl<E> ClippedSurfaceRenderElement<E>
|
||||
where
|
||||
E: RenderElement<R>,
|
||||
R: NiriRenderer,
|
||||
E: Element,
|
||||
{
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
elem: E,
|
||||
view_src: Rectangle<f64, Logical>,
|
||||
@@ -47,6 +44,8 @@ where
|
||||
geometry: Rectangle<f64, Logical>,
|
||||
program: GlesTexProgram,
|
||||
corner_radius: CornerRadius,
|
||||
alpha_tex: Option<GlesTexture>,
|
||||
ignore_alpha: f64,
|
||||
) -> Self {
|
||||
let elem_geo = elem.geometry(scale);
|
||||
|
||||
@@ -80,20 +79,25 @@ where
|
||||
* Mat3::from_scale(buf_size / src_size)
|
||||
* Mat3::from_translation(-src_loc / buf_size);
|
||||
|
||||
let uniforms = vec![
|
||||
let mut uniforms = vec![
|
||||
Uniform::new("niri_scale", scale.x as f32),
|
||||
Uniform::new("geo_size", (geometry.size.w as f32, geometry.size.h as f32)),
|
||||
Uniform::new("corner_radius", <[f32; 4]>::from(corner_radius)),
|
||||
mat3_uniform("input_to_geo", input_to_geo),
|
||||
];
|
||||
|
||||
if alpha_tex.is_some() && ignore_alpha > 0. {
|
||||
uniforms.push(Uniform::new("alpha_tex", 1));
|
||||
uniforms.push(Uniform::new("ignore_alpha", ignore_alpha as f32));
|
||||
}
|
||||
|
||||
Self {
|
||||
inner: elem,
|
||||
program,
|
||||
corner_radius,
|
||||
geometry,
|
||||
uniforms,
|
||||
marker: PhantomData,
|
||||
alpha_tex,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,10 +152,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, R> Element for ClippedSurfaceRenderElement<E, R>
|
||||
impl<E> Element for ClippedSurfaceRenderElement<E>
|
||||
where
|
||||
E: RenderElement<R>,
|
||||
R: NiriRenderer,
|
||||
E: Element,
|
||||
{
|
||||
fn id(&self) -> &Id {
|
||||
self.inner.id()
|
||||
@@ -226,7 +229,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> RenderElement<GlesRenderer> for ClippedSurfaceRenderElement<E, GlesRenderer>
|
||||
impl<E> RenderElement<GlesRenderer> for ClippedSurfaceRenderElement<E>
|
||||
where
|
||||
E: RenderElement<GlesRenderer>,
|
||||
{
|
||||
@@ -239,6 +242,16 @@ where
|
||||
opaque_regions: &[Rectangle<i32, Physical>],
|
||||
) -> Result<(), GlesError> {
|
||||
frame.override_default_tex_program(self.program.clone(), self.uniforms.clone());
|
||||
|
||||
if let Some(alpha_tex) = &self.alpha_tex {
|
||||
frame.with_context(|gl| unsafe {
|
||||
gl.ActiveTexture(ffi::TEXTURE1);
|
||||
gl.BindTexture(ffi::TEXTURE_2D, alpha_tex.tex_id());
|
||||
gl.TexParameteri(ffi::TEXTURE_2D, ffi::TEXTURE_MIN_FILTER, ffi::LINEAR as i32);
|
||||
gl.TexParameteri(ffi::TEXTURE_2D, ffi::TEXTURE_MAG_FILTER, ffi::LINEAR as i32);
|
||||
})?;
|
||||
}
|
||||
|
||||
RenderElement::<GlesRenderer>::draw(&self.inner, frame, src, dst, damage, opaque_regions)?;
|
||||
frame.clear_tex_program_override();
|
||||
Ok(())
|
||||
@@ -251,8 +264,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'render, E> RenderElement<TtyRenderer<'render>>
|
||||
for ClippedSurfaceRenderElement<E, TtyRenderer<'render>>
|
||||
impl<'render, E> RenderElement<TtyRenderer<'render>> for ClippedSurfaceRenderElement<E>
|
||||
where
|
||||
E: RenderElement<TtyRenderer<'render>>,
|
||||
{
|
||||
@@ -267,6 +279,16 @@ where
|
||||
frame
|
||||
.as_gles_frame()
|
||||
.override_default_tex_program(self.program.clone(), self.uniforms.clone());
|
||||
|
||||
if let Some(alpha_tex) = &self.alpha_tex {
|
||||
frame.as_gles_frame().with_context(|gl| unsafe {
|
||||
gl.ActiveTexture(ffi::TEXTURE1);
|
||||
gl.BindTexture(ffi::TEXTURE_2D, alpha_tex.tex_id());
|
||||
gl.TexParameteri(ffi::TEXTURE_2D, ffi::TEXTURE_MIN_FILTER, ffi::LINEAR as i32);
|
||||
gl.TexParameteri(ffi::TEXTURE_2D, ffi::TEXTURE_MAG_FILTER, ffi::LINEAR as i32);
|
||||
})?;
|
||||
}
|
||||
|
||||
RenderElement::draw(&self.inner, frame, src, dst, damage, opaque_regions)?;
|
||||
frame.as_gles_frame().clear_tex_program_override();
|
||||
Ok(())
|
||||
|
||||
@@ -28,30 +28,9 @@ varying vec2 v_coords;
|
||||
|
||||
uniform vec4 geo;
|
||||
uniform vec2 output_size;
|
||||
uniform float corner_radius;
|
||||
uniform float noise;
|
||||
uniform float ignore_alpha;
|
||||
|
||||
float rounding_alpha(vec2 coords, vec2 size, float radius) {
|
||||
vec2 center;
|
||||
|
||||
if (coords.x < radius && coords.y < radius) {
|
||||
center = vec2(radius, radius);
|
||||
} else if (coords.x > size.x - radius && coords.y < radius) {
|
||||
center = vec2(size.x - radius, radius);
|
||||
} else if (coords.x > size.x - radius && coords.y > size.y - radius) {
|
||||
center = vec2(size.x - radius, size.y - radius);
|
||||
} else if (coords.x < radius && coords.y > size.y - radius) {
|
||||
center = vec2(radius, size.y - radius);
|
||||
} else {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
float dist = distance(coords, center);
|
||||
float half_px = 0.5 ;
|
||||
return 1.0 - smoothstep(radius - half_px, radius + half_px, dist);
|
||||
}
|
||||
|
||||
// Noise function copied from hyprland.
|
||||
// I like the effect it gave, can be tweaked further
|
||||
float hash(vec2 p) {
|
||||
@@ -79,19 +58,10 @@ void main() {
|
||||
color = vec4(color.rgb, 1.0);
|
||||
#endif
|
||||
|
||||
// This shader exists to make blur rounding correct.
|
||||
//
|
||||
// Since we are scr-ing a texture that is the size of the output, the v_coords are always
|
||||
// relative to the output. This corresponds to gl_FragCoord.
|
||||
vec2 size = geo.zw;
|
||||
// NOTE: this is incorrect when rendering in winit, since y is inverted,
|
||||
// but on tty produces the correct result, which is all that matters
|
||||
vec2 loc = gl_FragCoord.xy - geo.xy;
|
||||
|
||||
if (noise > 0.0) {
|
||||
// Add noise fx
|
||||
// This can be used to achieve a glass look
|
||||
float noiseHash = hash(loc / size);
|
||||
float noiseHash = hash(v_coords);
|
||||
float noiseAmount = (mod(noiseHash, 1.0) - 0.5);
|
||||
color.rgb += noiseAmount * noise;
|
||||
}
|
||||
@@ -102,11 +72,6 @@ void main() {
|
||||
discard;
|
||||
}
|
||||
|
||||
// Apply corner rounding inside geometry.
|
||||
if (corner_radius > 0.0) {
|
||||
color *= rounding_alpha(loc, size, corner_radius);
|
||||
}
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,12 @@ uniform samplerExternalOES tex;
|
||||
uniform sampler2D tex;
|
||||
#endif
|
||||
|
||||
#if defined(EXTERNAL)
|
||||
uniform samplerExternalOES alpha_tex;
|
||||
#else
|
||||
uniform sampler2D alpha_tex;
|
||||
#endif
|
||||
|
||||
uniform float alpha;
|
||||
varying vec2 v_coords;
|
||||
|
||||
@@ -25,6 +31,7 @@ uniform float niri_scale;
|
||||
uniform vec2 geo_size;
|
||||
uniform vec4 corner_radius;
|
||||
uniform mat3 input_to_geo;
|
||||
uniform float ignore_alpha;
|
||||
|
||||
float rounding_alpha(vec2 coords, vec2 size) {
|
||||
vec2 center;
|
||||
@@ -52,6 +59,17 @@ float rounding_alpha(vec2 coords, vec2 size) {
|
||||
}
|
||||
|
||||
void main() {
|
||||
if (alpha <= 0.0) {
|
||||
discard;
|
||||
}
|
||||
|
||||
if (ignore_alpha > 0.0) {
|
||||
vec4 alpha_color = texture2D(alpha_tex, v_coords);
|
||||
if (alpha_color.a < ignore_alpha) {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
|
||||
vec3 coords_geo = input_to_geo * vec3(v_coords, 1.0);
|
||||
|
||||
// Sample the texture.
|
||||
|
||||
@@ -88,6 +88,8 @@ impl Shaders {
|
||||
UniformName::new("geo_size", UniformType::_2f),
|
||||
UniformName::new("corner_radius", UniformType::_4f),
|
||||
UniformName::new("input_to_geo", UniformType::Matrix3x3),
|
||||
UniformName::new("alpha_tex", UniformType::_1i),
|
||||
UniformName::new("ignore_alpha", UniformType::_1f),
|
||||
],
|
||||
)
|
||||
.map_err(|err| {
|
||||
@@ -105,13 +107,8 @@ impl Shaders {
|
||||
.compile_custom_texture_shader(
|
||||
include_str!("blur_finish.frag"),
|
||||
&[
|
||||
UniformName::new("output_size", UniformType::_2f),
|
||||
UniformName::new("corner_radius", UniformType::_1f),
|
||||
UniformName::new("alpha", UniformType::_1f),
|
||||
UniformName::new("noise", UniformType::_1f),
|
||||
UniformName::new("geo", UniformType::_4f),
|
||||
UniformName::new("ignore_alpha", UniformType::_1f),
|
||||
UniformName::new("alpha_tex", UniformType::_1i),
|
||||
],
|
||||
)
|
||||
.map_err(|e| warn!("error compiling clipped surface shader: {e:?}"))
|
||||
|
||||
@@ -112,7 +112,7 @@ pub enum MruCloseRequest {
|
||||
niri_render_elements! {
|
||||
ThumbnailRenderElement<R> => {
|
||||
LayoutElement = LayoutElementRenderElement<R>,
|
||||
ClippedSurface = ClippedSurfaceRenderElement<WaylandSurfaceRenderElement<R>, R>,
|
||||
ClippedSurface = ClippedSurfaceRenderElement<WaylandSurfaceRenderElement<R>>,
|
||||
Border = BorderRenderElement,
|
||||
}
|
||||
}
|
||||
@@ -401,6 +401,8 @@ impl Thumbnail {
|
||||
geo,
|
||||
shader.clone(),
|
||||
radius,
|
||||
None,
|
||||
0.,
|
||||
);
|
||||
return ThumbnailRenderElement::ClippedSurface(elem);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user