fix(blur): consider output transform in certain situations

This commit is contained in:
2025-11-26 11:03:38 +01:00
parent 0ce4d0209c
commit 9e247cb426
7 changed files with 58 additions and 58 deletions

View File

@@ -26,6 +26,7 @@
withDinit ? false,
withScreencastSupport ? true,
withSystemd ? true,
self,
}:
let
cargoToml = builtins.fromTOML (builtins.readFile ../../../Cargo.toml);
@@ -188,6 +189,12 @@ craneLib'.buildPackage (
};
};
env =
craneBuildArgs.env
// (lib.optionalAttrs (self ? rev) {
NIRI_BUILD_COMMIT = self.rev;
});
meta = {
description = "Scrollable-tiling Wayland compositor";
homepage = "https://github.com/YaLTeR/niri";

View File

@@ -1324,8 +1324,7 @@ impl Tty {
}
let render_node = device.render_node.unwrap_or(self.primary_render_node);
let mut renderer = self.gpu_manager.single_renderer(&render_node)?;
EffectsFramebuffers::init_for_output(output.clone(), &mut renderer);
let renderer = self.gpu_manager.single_renderer(&render_node)?;
let egl_context = renderer.as_ref().egl_context();
let render_formats = egl_context.dmabuf_render_formats();
@@ -1477,6 +1476,9 @@ impl Tty {
niri.add_output(output.clone(), Some(refresh_interval(mode)), vrr_enabled);
let mut renderer = self.gpu_manager.single_renderer(&render_node)?;
EffectsFramebuffers::init_for_output(&output, &mut renderer, None);
if niri.monitors_active {
// Redraw the new monitor.
niri.event_loop.insert_idle(move |state| {
@@ -2430,7 +2432,7 @@ impl Tty {
match renderer {
Ok(mut renderer) => {
if let Err(e) =
EffectsFramebuffers::update_for_output(&output, &mut renderer)
EffectsFramebuffers::update_for_output(&output, &mut renderer, None)
{
warn!("failed to update fx buffers after output resize: {e:?}");
} else {

View File

@@ -128,6 +128,7 @@ impl Winit {
if let Err(e) = EffectsFramebuffers::update_for_output(
&winit.output,
winit.backend.renderer(),
None,
) {
warn!("failed to update fx buffers on output resize: {e:?}");
} else {
@@ -159,7 +160,7 @@ impl Winit {
resources::init(renderer);
shaders::init(renderer);
RendererData::init(renderer);
EffectsFramebuffers::init_for_output(self.output.clone(), renderer);
EffectsFramebuffers::init_for_output(&self.output, renderer, None);
let config = self.config.borrow();
if let Some(src) = config.animations.window_resize.custom_shader.as_deref() {

View File

@@ -1709,14 +1709,10 @@ impl State {
});
let scale = closest_representable_scale(scale.clamp(0.1, 10.));
let mut transform = panel_orientation(output)
let transform = panel_orientation(output)
+ config
.map(|c| ipc_transform_to_smithay(c.transform))
.unwrap_or(Transform::Normal);
// FIXME: fix winit damage on other transforms.
if name.connector == "winit" {
transform = Transform::Flipped180;
}
if output.current_scale().fractional_scale() != scale
|| output.current_transform() != transform
@@ -3037,7 +3033,7 @@ impl Niri {
});
let scale = closest_representable_scale(scale.clamp(0.1, 10.));
let mut transform = panel_orientation(&output)
let transform = panel_orientation(&output)
+ c.map(|c| ipc_transform_to_smithay(c.transform))
.unwrap_or(Transform::Normal);
@@ -3047,11 +3043,6 @@ impl Niri {
.to_array_unpremul();
backdrop_color[3] = 1.;
// FIXME: fix winit damage on other transforms.
if name.connector == "winit" {
transform = Transform::Flipped180;
}
let mut layout_config = c.and_then(|c| c.layout.clone());
// Support the deprecated non-layout background-color key.
if let Some(layout) = &mut layout_config {

View File

@@ -73,7 +73,7 @@ pub struct EffectsFramebuffers {
current_buffer: CurrentBuffer,
/// Size of the output that this object runs on.
output_size: Size<i32, Physical>,
/// The transform to be used for rendering the blur texture.
/// Transform of the output.
transform: Transform,
}
@@ -83,15 +83,6 @@ fn get_rerender_at() -> Option<Instant> {
Some(Instant::now() + Duration::from_millis(150))
}
fn transform_for_texture(t: Transform) -> Transform {
match t {
Transform::Normal | Transform::Flipped180 => Transform::Normal,
Transform::_90 | Transform::Flipped270 => Transform::_90,
Transform::_180 | Transform::Flipped => Transform::_180,
Transform::_270 | Transform::Flipped90 => Transform::_270,
}
}
impl EffectsFramebuffers {
/// Get the associated [`EffectsFramebuffers`] with this output.
pub fn get<'a>(output: &'a Output) -> Option<RefMut<'a, Self>> {
@@ -120,28 +111,30 @@ impl EffectsFramebuffers {
///
/// The framebuffers handles live inside the Output's user data, use [`Self::get`] to access
/// them.
pub fn init_for_output(output: Output, renderer: &mut impl NiriRenderer) {
pub fn init_for_output(
output: &Output,
renderer: &mut impl NiriRenderer,
orientation: Option<Transform>,
) {
let renderer = renderer.as_gles_renderer();
let output_size = output.current_mode().unwrap().size;
let transform = orientation.unwrap_or_else(|| output.current_transform());
let texture_size = transform.transform_size(output.current_mode().unwrap().size);
fn create_buffer(
renderer: &mut GlesRenderer,
size: Size<i32, Physical>,
) -> Result<GlesTexture, GlesError> {
let create_buffer = |renderer: &mut GlesRenderer, size: Size<i32, Physical>| {
renderer.create_buffer(
Format::Abgr8888,
size.to_logical(1).to_buffer(1, Transform::Normal),
)
}
};
let this = EffectsFramebuffers {
optimized_blur: create_buffer(renderer, output_size).unwrap(),
optimized_blur: create_buffer(renderer, texture_size).unwrap(),
optimized_blur_rerender_at: get_rerender_at(),
effects: create_buffer(renderer, output_size).unwrap(),
effects_swapped: create_buffer(renderer, output_size).unwrap(),
effects: create_buffer(renderer, texture_size).unwrap(),
effects_swapped: create_buffer(renderer, texture_size).unwrap(),
current_buffer: CurrentBuffer::Normal,
output_size: output.current_mode().unwrap().size,
transform: transform_for_texture(output.current_transform()),
output_size: texture_size,
transform,
};
let user_data = output.user_data();
@@ -157,32 +150,32 @@ impl EffectsFramebuffers {
pub fn update_for_output(
output: &Output,
renderer: &mut impl NiriRenderer,
orientation: Option<Transform>,
) -> Result<(), GlesError> {
let renderer = renderer.as_gles_renderer();
let Some(mut fx_buffers) = Self::get(output) else {
warn!("attempting to update fx buffer on output that has none: {output:?}");
return Ok(()); // TODO: error?
};
let output_size = output.current_mode().unwrap().size;
fn create_buffer(
renderer: &mut GlesRenderer,
size: Size<i32, Physical>,
) -> Result<GlesTexture, GlesError> {
let transform = orientation.unwrap_or_else(|| output.current_transform());
let texture_size = transform.transform_size(output.current_mode().unwrap().size);
let create_buffer = |renderer: &mut GlesRenderer, size: Size<i32, Physical>| {
renderer.create_buffer(
Format::Abgr8888,
size.to_logical(1).to_buffer(1, Transform::Normal),
)
}
};
*fx_buffers = EffectsFramebuffers {
optimized_blur: create_buffer(renderer, output_size)?,
optimized_blur: create_buffer(renderer, texture_size)?,
optimized_blur_rerender_at: get_rerender_at(),
effects: create_buffer(renderer, output_size)?,
effects_swapped: create_buffer(renderer, output_size)?,
effects: create_buffer(renderer, texture_size)?,
effects_swapped: create_buffer(renderer, texture_size)?,
current_buffer: CurrentBuffer::Normal,
output_size: output.current_mode().unwrap().size,
transform: transform_for_texture(output.current_transform()),
output_size: texture_size,
transform,
};
Ok(())
@@ -230,7 +223,7 @@ impl EffectsFramebuffers {
&mut fb,
self.output_size,
scale,
self.transform,
Transform::Normal,
elements.iter(),
)
.expect("failed to render for optimized blur buffer");
@@ -363,6 +356,8 @@ pub(super) unsafe fn get_main_buffer_blur(
}
{
// TODO: need to rotate blur texture on transformed screens
// NOTE: We are assured that the size of the effects texture is the same
// as the bound fbo size, so blitting uses dst immediately
gl.BindFramebuffer(ffi::DRAW_FRAMEBUFFER, sample_fbo);
@@ -426,6 +421,7 @@ pub(super) unsafe fn get_main_buffer_blur(
0.5 / (tex_size.w as f32 / 2.0),
0.5 / (tex_size.h as f32 / 2.0),
];
for i in 0..passes {
let (sample_buffer, render_buffer) = fx_buffers.buffers();
let damage = dst_expanded.downscale(1 << (i + 1));

View File

@@ -30,6 +30,7 @@ pub enum BlurRenderElement {
noise: f32,
scale: f64,
output_size: Size<i32, Physical>,
output_transform: Transform,
},
/// Use true blur.
///
@@ -100,6 +101,7 @@ impl BlurRenderElement {
noise: config.noise.0 as f32,
scale,
output_size: fx_buffers.output_size,
output_transform: fx_buffers.transform,
}
}
@@ -304,7 +306,7 @@ fn draw_true_blur(
dst,
damage,
opaque_regions,
fx_buffers.transform,
Transform::Normal,
alpha,
program.as_ref(),
&additional_uniforms,
@@ -327,6 +329,7 @@ impl RenderElement<GlesRenderer> for BlurRenderElement {
noise,
scale,
output_size,
output_transform,
} => {
let downscaled_dst = Rectangle::new(
dst.loc,
@@ -348,16 +351,17 @@ impl RenderElement<GlesRenderer> for BlurRenderElement {
} else {
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",
[
dst.loc.x as f32,
dst.loc.y as f32,
dst.size.w as f32,
dst.size.h as f32,
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),

View File

@@ -71,10 +71,9 @@ void main() {
// 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;
vec2 loc;
loc.x = gl_FragCoord.x - geo.x;
// FIXME: y inverted
loc.y = output_size.y - (gl_FragCoord.y + geo.y);
// 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;
// Add noise fx
// This can be used to achieve a glass look