Conversation
| use smithay::utils::{Logical, Rectangle}; | ||
| use smithay::wayland::compositor::{RectangleKind, RegionAttributes}; | ||
|
|
||
| pub fn region_to_non_overlapping_rects( |
There was a problem hiding this comment.
Heya, I also implemented the kde blur and ext-background-effect protcols in my fork.
While doing that, I noticed that a lot of clients just define a single rectangle as their region, which encompasses the entire window / layer. This led to me developing this helper utility:
The helper exists mainly to avoid having to allocate an extra Vec for clients that only define one rectangle. There are other optimizations as well that help for checking whether a region changed (and then not re-render blur if that's the case), but those may not be applicable in your case.
Feel free to take a look and see if it's useful for you.
There was a problem hiding this comment.
Hey, guess this is more of a Smithay question because it already gives us a pre-allocated Vec: https://smithay.github.io/smithay/smithay/wayland/background_effect/struct.BackgroundEffectSurfaceCachedState.html
As for KDE-blur, I probably won't keep the impl in niri so it doesn't matter.
Other than that, in this PR I already made the computations as lazy as possible, so the non-overlapping region is only computed when the window-submitted wl_region actually changes, and only when it's first needed. And changes to the region don't cause blur re-renders.
|
setting 2026-02-21.14-22-33.mp42026-02-21.14-25-18.mp4 |
|
Yes, that's one of the known limitations of non-xray:
|
I'll have to think if there's a non-cursed way of delaying the xray change until the end of the animation, but probably there isn't any non-cursed way |
hm? |
|
Yeah but the default value is 0.02, ofc if you make it higher it will be more visible. Is it noticeable at lower values or do you need higher values for some reason? |
|
Might be good to add foot to the list of programs with ext-background-effect-v1 support in progress: https://codeberg.org/dnkl/foot/pulls/2198 |
For me, the 0.02 setting at 4k and 2.4K screen resolutions is not noticeable, even when looking closely for it. I had to take a screenshot and zoom in really far to be able to see any noise patterns. |
|
Dude! I hope this gets pulled and gets released soon! Using Noctalia, it would make everything look amazing |
|
I was experimenting with blurring Firefox using this customChrome.css together with the following window rule in niri (Firefox 147 with vertical sidebar enabled): window-rule {
match app-id="firefox"
background-effect {
blur true
}
}Everything works fine at first. However, whenever I expand the vertical sidebar (either by making it to show full tab titles or by clicking the settings/bookmarks icons on the sidebar), strange glitchy black pixels appear in the background of the expanded sidebar. Sometimes black pixels also show up when I move the mouse over that area. Interestingly, switching to another window and then back to Firefox resolves the glitch: the blur is applied correctly again with no visible artifacts. However, this fix is only temporary: as soon as I hide the sidebar again, switch to another window and back, and then re-expand the sidebar, the glitchy black pixels reappear. One additional clue that might help narrow it down: whenever I take a screenshot or record a video of the glitched area, the captured image/video correctly shows the blur with no black pixel artifacts at all. I'm not sure whether this is a firefox quirk or something on niri's side. I figured it could be worth bringing it up here first in case these are indeed artifacts that shouldn't be happening. |
This is usually a clientside bug when the client tells niri that some part of a Wayland surface is fully opaque when it isn't. GTK 3 tends to do this with rounded surfaces and the usual fix is to make them have background opacity 0.99 instead of 1. Firefox does custom Wayland handling, so not sure how you can fix it there. You can check that this is the issue by binding https://niri-wm.github.io/niri/Configuration%3A-Debug-Options.html#debug-toggle-opaque-regions then seeing if the surface in question is blue (which is opaque) instead of red (semitransparent). |
Thanks! Yeah, indeed I noticed that the expanded region isn't fully red. It's a bit bluish compared to the titlebar and the unchanged sidebar region. Also, can confirm that setting background opacity to 0.99 fixes the problem. |
This should now be fixed, hopefully without any regressions. |
|
Being able to additionally change the contrast instead of only saturation would be nice to have |
|
What's the usecase? |
Why not both? |
I think the issue is more that there is a obvious repeating pattern it isn't random never noticed this on Hyprland when setting the noise higher Regardless, tested it and it's working well so far besides Quickshell/DMS not supporting ext-background-effect |
Yeah, this is just what this noise looks like, that I picked for niri (Interleaved Gradient Noise). Upsides are that it's extremely cheap and is supposed to work well specifically for dithering (which is kinda what it's used for in niri). So unless it's problematic I'd like to leave it as is |
Having noise for the visuals can be kinda nice as well so both would be ideal, obviously not as extreme as that screenshot but I have used noise at a higher level that this would be noticeable really worked with one wallpaper I had at some point |
Would a gradual fade animation (spawn, no blur -> full blur) make sense here? Would delay the actual blur effect a bit but also make the pop-in less noticeable. |
I'm afraid this doesn't help the technical challenge here, in fact even makes it a bit more cursed |
This non-xray limitation is now fixed, but this (admittedly quite rare) case is currently not optimized (waiting for more fixes to the Smithay PR). |
|
In what color space is the blur being performed? From a glance at the shaders it looks like it's plain sRGB. Wouldn't we want something like minutephysics has a classic video on why blending colors in gamma space (e.g. sRGB) is wrong: https://www.youtube.com/watch?v=LKnqECcg6Gw. |
But srgb-linear is not really nice when looking at the human eye. It maybe avoids the muddy color in between, but also creates very strange gradients for example from white to black:
In this case the color in the middle is already very very bright for the human eye. Even though it is "linear" from a photon intensity perspective, it is not from the point of the human eye reading it. I would propose to maybe use a different color space such as oklab or similar? They solve the muddy problem, but also stay more close to how the human eye reads gradients. A good example of gradients in different color spaces can be found on this website: |
You'd just have to convert the texture back from linear srgb to the output's color space once the blur is finished (sRGB for niri's case, I don't believe any others are supported). It will look correct as long as the blending is performed in a linear color space. The reason oklab and similar colour spaces exist is because gradients should be performed in a perceptual colour space as that better fits with designer expectations (keeping saturation, light levels constant, etc), but blending should be physically accurate instead. |
Honestly, I'd rather take something that requires the least amount of calculations. While doing more to make it look prettier is fine for blurring single image, this is a dynamic setting. If you have an animated wallpaper or desktop widgets that update in real time, doing additional calculations on a high resolution screen can be really bad for performance. I work on a PC with integrated graphics and 5120x1440 monitor that already struggles with blur during animations (going in/out of the overview, switching workspaces, etc). |
|
Maybe colorspace should be configurable if the trade-off between accuracy and performance is significant. |
|
Upon more reading, the way to do this would be to use OpenGL's |
To have it in one place.
Simplified clamping exploiting half_px + half_px = 1.0 / niri_scale. Makes the resize shader fit on a Eee PC ALU.
Changes in geometry already cause a repaint.
The fixes in question were implemented, so I updated this blur PR accordingly. Had to do a bit of a surgery on our wlr-screencopy and PipeWire screencast impl to support it properly, but I think it works now with no excessive perf loss from multiple clones of layer surfaces with non-xray blur in the Overview. Please test that nothing broke, especially with regards to screencasting an output that has non-xray blur, and especially when it's also on top of a blocked-out window. Blocked-out window contents should never leak into the stream in any way, and the non-xray blur should draw without artifacts. Re. sRGB talk: let's not complicate the math and shaders until there's an actual problem. I'm also pretty sure KDE also does it in the usual sRGB space. |
Will likely drop this commit as even KDE removed this protocol in favor of ext-background-effect: https://invent.kde.org/plasma/kwin/-/merge_requests/8798







Well, looks like I'm ready to promote this branch to a pull request. All planned features are implemented, all bugs that I knew about and wanted to fix should be fixed.
Please test and report any problems and suggestions. See the docs at https://github.com/niri-wm/niri/blob/wip/branch/docs/wiki/Window-Effects.md.
There's no "alpha threshold" setting for blur, instead clients are encouraged to implement the
ext-background-effectprotocol which lets them shape their background blur. It's already implemented, or in progress, in:Note
Currently, this PR doesn't implement
ext-background-effectfor popups and subsurfaces. This is mainly because I don't have any clients that do this to test with. If some client can do it I'll look into it.This PR also implements the KDE blur protocol which makes a bunch of other clients work (Alacritty, kitty, etc.) but I'll remove it before merging because even KDE has dropped it in favor of ext-background-effect.
Background blur turned out to be a massive undertaking. Not because of blur itself, but because window background effects in general required a lot of thinking and additions to the code, especially to make them as efficient as possible. Xray and non-xray background effects, both of which this PR implements, are also pretty much two entirely separate and very different beasts, both of which I had to get working with all other niri features (like block-out-from).
What's left is some code cleanups, and maybe splitting the commits a bit further.
Non-xray might land a bit later than xray because it depends on a WIP Smithay PR.
Implements #54, supersedes #1634. Thanks @visualglitch91 for rebasing and maintaining the previous blur PR all this time!