forked from Mirror/niri
fix(blur): consider output transform in certain situations
This commit is contained in:
@@ -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";
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
13
src/niri.rs
13
src/niri.rs
@@ -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 {
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user