Skip to content

Conversation

@the-eater
Copy link
Contributor

@the-eater the-eater commented Oct 19, 2025

Currently the blur applied to nodes is Locally Sourced Free Range Blur. which is fine if there's e.g. only 1 thing in a vacuum needing to be blurred. but when other things need to be blurred too that are rendered next to it, it causes the issue that the blur leaks into each other, object A will first blur, then object B will sample the existing rendered frame for its own blur.

This causes mostly positional darkness on most blurred backgrounds.

The solution provided in this PR, is to have a dedicated node that gets rendered before -anything- else, which will then pre-render the blur to a texture

This node is called "blur source" as, it will be the source of blur for other nodes

A node (limited to rect and buffer atm, as they are only receiving ends of blur) can be added as a target to the blur, this will establish a link between the node and the blur source, allowing us to limit the region we blur / disable the blur dynamically if no nodes are actually doing blurring

An example of the results with my swayfx PR

Before After Difference
20251020_16h41m52s_grim 20251020_16h44m28s_grim Diff

This PR doesn't change old blurring code, it merely splits the code apart so a texture can be fed to the blur pass and reused.

Performance should be the exact same for everything, (with exception of my PR which should see minimal improved performance because blurring is only done once instead of being ran, 5-8 times per container)

Todo:

  • Reduce region to render blur based on listed and enabled blur
  • Add flags to disable/enable blur for node
  • Detect when blur is outside of blur source region, and let it fallback to local blur

Credits

linked_node.c/h is from #135 by @ErikReider, I simply added the linked_node_list

@the-eater the-eater force-pushed the blur-source branch 2 times, most recently from bb262ba to 3a65371 Compare October 20, 2025 14:26
@the-eater
Copy link
Contributor Author

Reducing region is, unclear as I need to know the absolute position of nodes 🤔

@the-eater the-eater marked this pull request as ready for review October 20, 2025 18:53
@WillPower3309
Copy link
Member

Looks like there are some conflicts, likely from the blur strength PR getting merged

@WillPower3309
Copy link
Member

I have another thought here, if you're willing to do a bit more work. What if we build off of this to finally make the blur its own node? It would no longer need to be part of the rect or texture nodes, and could be moved, clipped, resized / whatever like other nodes. It would still need to be linked to a buffer to support transparent discarding (and the opaque damage tracking optimization). I think it'd be easier for compositors to work with that, and it would really clean up our buffer and rect node rendering

@WillPower3309
Copy link
Member

I have another thought here, if you're willing to do a bit more work. What if we build off of this to finally make the blur its own node? It would no longer need to be part of the rect or texture nodes, and could be moved, clipped, resized / whatever like other nodes. It would still need to be linked to a buffer to support transparent discarding (and the opaque damage tracking optimization). I think it'd be easier for compositors to work with that, and it would really clean up our buffer and rect node rendering

In this way, swayfx could have one blur node per container, and resize it from the surface size to the surface + decoration size based on if the borders / titlebar are transparent or not. The blur node would then be rendered below the container.

@the-eater
Copy link
Contributor Author

I have another thought here, if you're willing to do a bit more work. What if we build off of this to finally make the blur its own node? It would no longer need to be part of the rect or texture nodes, and could be moved, clipped, resized / whatever like other nodes. It would still need to be linked to a buffer to support transparent discarding (and the opaque damage tracking optimization). I think it'd be easier for compositors to work with that, and it would really clean up our buffer and rect node rendering

That sounds trivial* with the code already there, and just breaking fx_render_pass_add_blur into fx_render_pass_add_blur and fx_render_pass_apply_blur. I think I can make that happen in the next few days

The question arises then of, do we want to replace the optimized blur node with another blur source node?

@the-eater
Copy link
Contributor Author

In this way, swayfx could have one blur node per container, and resize it from the surface size to the surface + decoration size based on if the borders / titlebar are transparent or not. The blur node would then be rendered below the container.

This is what my swayfx branch currently does Asterisk (the-eater/swayfx@fb3f54e), I was hoping to be dynamically change the render region of the blur by looking at its targets. This would reduce the workload for implementers, and the blur just needs to be set to be big Enough and things will Just Work

@WillPower3309
Copy link
Member

WillPower3309 commented Oct 22, 2025

I have another thought here, if you're willing to do a bit more work. What if we build off of this to finally make the blur its own node? It would no longer need to be part of the rect or texture nodes, and could be moved, clipped, resized / whatever like other nodes. It would still need to be linked to a buffer to support transparent discarding (and the opaque damage tracking optimization). I think it'd be easier for compositors to work with that, and it would really clean up our buffer and rect node rendering

That sounds trivial* with the code already there, and just breaking fx_render_pass_add_blur into fx_render_pass_add_blur and fx_render_pass_apply_blur. I think I can make that happen in the next few days

The question arises then of, do we want to replace the optimized blur node with another blur source node?

The answer would be yes, we'd likely still need a different node for optimized blur. For the new blur node, the fields should be:

  • strength
  • alpha
  • corner_radius
  • width
  • height
  • texture_mask (the texture we'd use for the blur stencil, can be NULL since we'd only use it for blur_ignore_transparent in swayfx)
  • is_optimized (should we render from the optimized_blur_buffer. We can probably find a better name for this one, should_only_blur_bottom_layer would work too and may be more descriptive)

@ErikReider
Copy link
Member

The answer would be yes, we'd likely still need a different node for optimized blur. For the new blur node, the fields should be:

  • strength

  • alpha

  • corner_radius

  • width

  • height

  • texture_mask (the texture we'd use for the blur stencil, can be NULL since we'd only use it for blur_ignore_transparent in swayfx)

  • is_optimized (should we render from the optimized_blur_buffer. We can probably find a better name for this one, should_only_blur_bottom_layer would work too and may be more descriptive)

We should also fix the stenciling when rotated :D

Copy link
Member

@WillPower3309 WillPower3309 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might not have communicated my previous comment well, but I think that right now this is going about blur nodes incorrectly. Instead of having a blur_source, we should completely remove blurring as part of the rect and buffer node rendering logic and create a blur node. Compositors can then move / clip / do whatever they like to this node. The blur node would just render a blurred texture of whatever is beneath it. We can move the backdrop_blur_optimized logic to it as well in order to just render the blur from the bottom layer. This would keep the optimized blur node, and would just be the optimized logic from the rect and buffer node rendering.

The transparent discarding could be hard to do correctly (and may be the one use case for requiring a linked_node), but if it causes any trouble, I'd rather you just remove it from the buffer and rect nodes along with the rest of the blur logic. I could then go ahead and add it back onto this branch as part of your blur node.

Ideally we'd have a completely decoupled blur node, and all blur logic purged from rect and buffer nodes. In fact, we shouldn't need the linked_node struct until we add back that transparent discarding. I'd suspect we should end up with more removed code than added code with this approach :)

Comment on lines 98 to 112
struct fx_render_blur_pass_options {
struct fx_render_texture_options tex_options;
pixman_region32_t *opaque_region;
struct fx_framebuffer *current_buffer;
struct blur_data *blur_data;
bool use_optimized_blur;
bool ignore_transparent;
float blur_strength;
};

struct fx_render_apply_blur_pass_options {
struct fx_render_texture_options tex_options;
pixman_region32_t *opaque_region;
bool ignore_transparent;
struct wlr_texture *blur_source;
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reasoning behind two different structs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because they're 2 different passes, that needed different inputs, and this made it clearer which pass needed which.

@the-eater
Copy link
Contributor Author

I see! that makes more sense, I think i really went all in on the concept that was stuck in my head! Time to try again, this time will be faster lmao.

The only worry I have is having 1 clipping rect not being adequate. and having a pixman_region as the render area might make things easier to selectively render?

@WillPower3309
Copy link
Member

I see! that makes more sense, I think i really went all in on the concept that was stuck in my head! Time to try again, this time will be faster lmao.

The only worry I have is having 1 clipping rect not being adequate. and having a pixman_region as the render area might make things easier to selectively render?

we really should revamp our clipping logic at some point, I like the idea of having a region instead of a box. For now though the box should be adequate. Either way this would likely replace #138

@WillPower3309 WillPower3309 linked an issue Nov 1, 2025 that may be closed by this pull request
@the-eater the-eater closed this Nov 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

create blur_node

3 participants