Respect translucent bar opacity and skip unnecessary blur

This commit is contained in:
Samuel Onoja committed 2026-09-27 12:41:24 +01:00
1 parent 23d84c0a77
commit cb512eece9
3 files changed
+46 -7

No files matched your search

+43 -4
View File
@@ -372,13 +372,14 @@ uniform float material_radius;
uniform vec2 texture_size; uniform vec2 texture_size;
uniform float blur_radius; uniform float blur_radius;
uniform float presentation_alpha; uniform float presentation_alpha;
uniform float background_opacity;
uniform vec4 tint; uniform vec4 tint;
varying vec2 v_coords; varying vec2 v_coords;
void main() { void main() {
vec2 half_size = visible_rect.zw * 0.5; vec2 half_size = visible_rect.zw * 0.5;
vec2 d = abs(gl_FragCoord.xy - visible_rect.xy - half_size) - (half_size - vec2(material_radius)); vec2 d = abs(gl_FragCoord.xy - visible_rect.xy - half_size) - (half_size - vec2(material_radius));
float sdf = length(max(d, 0.0)) + min(max(d.x, d.y), 0.0) - material_radius; float sdf = length(max(d, 0.0)) + min(max(d.x, d.y), 0.0) - material_radius;
float coverage = alpha * presentation_alpha * (1.0 - smoothstep(-0.5, 0.5, sdf)); float coverage = alpha * presentation_alpha * background_opacity * (1.0 - smoothstep(-0.5, 0.5, sdf));
if (coverage <= 0.0) { gl_FragColor = vec4(0.0); return; } if (coverage <= 0.0) { gl_FragColor = vec4(0.0); return; }
// Denser Gaussian sampling preserves the same radius and softness without // Denser Gaussian sampling preserves the same radius and softness without
// the visible grid left by widely spaced taps on detailed wallpapers. // the visible grid left by widely spaced taps on detailed wallpapers.
@@ -578,6 +579,7 @@ pub(crate) struct MaterialProgram(GlesPixelProgram);
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
struct MaterialParameters { struct MaterialParameters {
presentation_alpha: f32, presentation_alpha: f32,
background_opacity: f32,
blur: f32, blur: f32,
scene_generation: u64, scene_generation: u64,
sample_geometry: Rectangle<i32, Logical>, sample_geometry: Rectangle<i32, Logical>,
@@ -2328,11 +2330,16 @@ fn material_element(
(geometry.loc.x, geometry.loc.y + offset_y.round() as i32).into(), (geometry.loc.x, geometry.loc.y + offset_y.round() as i32).into(),
geometry.size, geometry.size,
); );
let blur = if material.style == crate::config::MaterialStyle::Translucent { let background_opacity = if role == crate::effects::SemanticRole::Panel {
state.theme_settings.backdrop_blur material.opacity
} else { } else {
0.0 1.0
}; };
let blur = material_blur_radius(
material.style,
material.opacity,
state.theme_settings.backdrop_blur,
);
let output_size = output let output_size = output
.current_transform() .current_transform()
.transform_size(mode.size) .transform_size(mode.size)
@@ -2343,6 +2350,7 @@ fn material_element(
let sample_physical = sample_geometry.to_physical_precise_round(scale); let sample_physical = sample_geometry.to_physical_precise_round(scale);
let parameters = MaterialParameters { let parameters = MaterialParameters {
presentation_alpha, presentation_alpha,
background_opacity,
blur: (blur * scale) as f32, blur: (blur * scale) as f32,
scene_generation: if blur > 0.0 { scene_generation: if blur > 0.0 {
state.backdrop_generation state.backdrop_generation
@@ -2485,6 +2493,14 @@ fn material_element(
Some((background, cached.shadow.clone().into())) Some((background, cached.shadow.clone().into()))
} }
fn material_blur_radius(style: crate::config::MaterialStyle, opacity: f32, radius: f64) -> f64 {
if style == crate::config::MaterialStyle::Translucent && opacity > 0.0 && opacity < 1.0 {
radius
} else {
0.0
}
}
fn blur_program(state: &mut Ferese, renderer: &mut GlesRenderer) -> Option<BlurProgram> { fn blur_program(state: &mut Ferese, renderer: &mut GlesRenderer) -> Option<BlurProgram> {
let context = renderer.context_id().erased(); let context = renderer.context_id().erased();
if let Some(program) = state.blur_programs.get(&context) { if let Some(program) = state.blur_programs.get(&context) {
@@ -2496,6 +2512,7 @@ fn blur_program(state: &mut Ferese, renderer: &mut GlesRenderer) -> Option<BlurP
UniformName::new("texture_size", UniformType::_2f), UniformName::new("texture_size", UniformType::_2f),
UniformName::new("blur_radius", UniformType::_1f), UniformName::new("blur_radius", UniformType::_1f),
UniformName::new("presentation_alpha", UniformType::_1f), UniformName::new("presentation_alpha", UniformType::_1f),
UniformName::new("background_opacity", UniformType::_1f),
UniformName::new("tint", UniformType::_4f), UniformName::new("tint", UniformType::_4f),
]; ];
match renderer.compile_custom_texture_shader(BLUR_SHADER, &uniforms) { match renderer.compile_custom_texture_shader(BLUR_SHADER, &uniforms) {
@@ -2525,6 +2542,7 @@ fn blur_uniforms(p: &MaterialParameters) -> Vec<Uniform<'static>> {
.into_owned(), .into_owned(),
Uniform::new("blur_radius", p.blur).into_owned(), Uniform::new("blur_radius", p.blur).into_owned(),
Uniform::new("presentation_alpha", p.presentation_alpha).into_owned(), Uniform::new("presentation_alpha", p.presentation_alpha).into_owned(),
Uniform::new("background_opacity", p.background_opacity).into_owned(),
Uniform::new("tint", p.tint).into_owned(), Uniform::new("tint", p.tint).into_owned(),
] ]
} }
@@ -2975,6 +2993,27 @@ mod tests {
assert!(removal_damage.iter().any(|rect| rect.contains((300, 180)))); assert!(removal_damage.iter().any(|rect| rect.contains((300, 180))));
} }
#[test]
fn fully_transparent_and_opaque_materials_skip_blur() {
use crate::config::MaterialStyle;
assert_eq!(
super::material_blur_radius(MaterialStyle::Translucent, 0.0, 18.0),
0.0
);
assert_eq!(
super::material_blur_radius(MaterialStyle::Translucent, 1.0, 18.0),
0.0
);
assert_eq!(
super::material_blur_radius(MaterialStyle::Translucent, 0.79, 18.0),
18.0
);
assert_eq!(
super::material_blur_radius(MaterialStyle::Solid, 0.79, 18.0),
0.0
);
}
#[test] #[test]
fn close_transform_scales_about_the_window_center() { fn close_transform_scales_about_the_window_center() {
let rect = ferese_layout::Rect::new(100.0, 50.0, 400.0, 300.0); let rect = ferese_layout::Rect::new(100.0, 50.0, 400.0, 300.0);
+1 -1
View File
@@ -162,7 +162,7 @@ these six visually distinct.
| Section / key | Type | Default | Meaning | | Section / key | Type | Default | Meaning |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| `theme.surface.bar.background` | color | `"#1C202EF2"` | Shell fallback background; compositor materials use `surface_base` | | `theme.surface.bar.background` | color | `"#1C202EF2"` | Shell fallback background; compositor materials use `surface_base` |
| `theme.surface.bar.opacity` | number 0–1 | omitted | Material opacity defaults to `0.78`; fallback retains background alpha | | `theme.surface.bar.opacity` | number 0–1 | omitted | Translucent bar background opacity, including blur; defaults to `0.78`. Text/icons stay opaque; 0 and 1 skip blur. Fallback retains background alpha |
| `theme.surface.bar.text_primary` | color | `"#F0F3FA"` | Bar text/icons | | `theme.surface.bar.text_primary` | color | `"#F0F3FA"` | Bar text/icons |
| `theme.surface.bar.text_muted` | color | `"#AAB4C7"` | Inactive bar foreground | | `theme.surface.bar.text_muted` | color | `"#AAB4C7"` | Inactive bar foreground |
| `theme.surface.popover.opacity` | number 0–1 | `0.96` | Shell popover fill alpha | | `theme.surface.popover.opacity` | number 0–1 | `0.96` | Shell popover fill alpha |
+2 -2
View File
@@ -730,9 +730,9 @@ pub fn fields(page: Page) -> Vec<Field> {
range( range(
"theme.surface.bar.opacity", "theme.surface.bar.opacity",
"Opacity", "Opacity",
"Lower values reveal more of the background.", "Background opacity for translucent bars, with or without blur. Text and icons stay opaque.",
0.78, 0.78,
0.2, 0.0,
1.0, 1.0,
0.01, 0.01,
"", "",