git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commitf7c07d38a010ac2989b4537296e4b29e20869828
parent5cf60a7046
authorLucas Galante <[email protected]>
date2026-06-29 22:13
Add output.scenefx_optimized_blur configuration support to toggle SceneFX optimized blur path

 src/server/config.rs             | 12 +++++++++++-
 src/server/layer_shell.rs        |  1 +
 src/server/window.rs             |  5 +++--
 src/server/wlroots_log_wrapper.c | 18 +++++++++++++-----
 src/server/xdg_toplevel.rs       |  1 +
 wrapper.h                        |  2 +-
 6 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/src/server/config.rs b/src/server/config.rs
index e2fdce8..396726b 100644
--- a/src/server/config.rs
+++ b/src/server/config.rs
@@ -44,6 +44,7 @@ pub struct Layout {
     pub desktop_grid_color: [f32; 4],
     pub desktop_grid_scale: f64,
     pub desktop_line_width: i32,
+    pub scenefx_optimized_blur: bool,
 }
 
 impl Default for Layout {
@@ -86,6 +87,7 @@ impl Default for Layout {
             desktop_grid_color: [1.0, 1.0, 1.0, 0.05],
             desktop_grid_scale: 100.0,
             desktop_line_width: 1,
+            scenefx_optimized_blur: true,
         }
     }
 }
@@ -203,12 +205,18 @@ pub struct GestureBind {
 pub struct OutputConfig {
     #[serde(default = "default_scale")]
     pub scale: f64,
+    #[serde(default = "default_scenefx_optimized_blur")]
+    pub scenefx_optimized_blur: bool,
 }
 
 fn default_scale() -> f64 {
     1.0
 }
 
+fn default_scenefx_optimized_blur() -> bool {
+    true
+}
+
 #[derive(Debug, Deserialize, Clone)]
 pub struct InputDeviceConfigRule {
     pub name: String,
@@ -1026,7 +1034,8 @@ fn parse_kdl_config(content: &str) -> Result<Config, String> {
     let mut output = None;
     if let Some(node) = doc.nodes().iter().find(|n| n.name().value() == "output") {
         let scale = get_child_arg_f64(node, "scale", 1.0);
-        output = Some(OutputConfig { scale });
+        let scenefx_optimized_blur = get_child_arg_bool(node, "scenefx_optimized_blur", true);
+        output = Some(OutputConfig { scale, scenefx_optimized_blur });
     }
 
     // 5. display
@@ -1202,6 +1211,7 @@ pub fn parse_config(path: &str, state: &mut crate::window_manager::WindowManager
     state.layout.status_background_blur = config.layout.status_background_blur as f32;
     state.layout.transparency_opacity = config.transparency.as_ref().and_then(|t| t.opacity).unwrap_or(0.9) as f32;
     state.layout.window_opacity = config.layout.window_opacity;
+    state.layout.scenefx_optimized_blur = config.output.as_ref().map(|o| o.scenefx_optimized_blur).unwrap_or(true);
 
     for (key, val) in &config.env {
         let expanded = expand_env_vars(val);
diff --git a/src/server/layer_shell.rs b/src/server/layer_shell.rs
index ccde5e5..4133111 100644
--- a/src/server/layer_shell.rs
+++ b/src/server/layer_shell.rs
@@ -594,6 +594,7 @@ unsafe extern "C" fn handle_layer_surface_commit(listener: *mut ffi::wl_listener
         ffi::river_scene_node_enable_blur(
             (*(*layer_surface).scene_layer_surface).tree as *mut ffi::wlr_scene_node,
             blur_enabled,
+            (*server).wm.layout.scenefx_optimized_blur,
         );
     }
 
diff --git a/src/server/window.rs b/src/server/window.rs
index 2c01ef5..e4770f7 100644
--- a/src/server/window.rs
+++ b/src/server/window.rs
@@ -1538,7 +1538,7 @@ impl Window {
                     blur_enabled = false;
                 }
             }
-            ffi::river_scene_node_enable_blur(self.surfaces.tree as *mut ffi::wlr_scene_node, blur_enabled);
+            ffi::river_scene_node_enable_blur(self.surfaces.tree as *mut ffi::wlr_scene_node, blur_enabled, (*self.server).wm.layout.scenefx_optimized_blur);
             ffi::river_scene_node_set_opacity(self.tree as *mut ffi::wlr_scene_node, requested.opacity);
 
             let radius = if requested.circular {
@@ -2743,7 +2743,8 @@ impl Decoration {
 
         self.surfaces.drop_saved();
 
-        ffi::river_scene_node_enable_blur(self.surfaces.tree as *mut ffi::wlr_scene_node, self.rendering_requested.blur);
+        let server = (*self.window).server;
+        ffi::river_scene_node_enable_blur(self.surfaces.tree as *mut ffi::wlr_scene_node, self.rendering_requested.blur, (*server).wm.layout.scenefx_optimized_blur);
 
         let scale = (*self.window).scale;
         let scaled_x = (self.rendering_requested.offset_x as f64 * scale) as i32;
diff --git a/src/server/wlroots_log_wrapper.c b/src/server/wlroots_log_wrapper.c
index 1cd1362..bb059c9 100644
--- a/src/server/wlroots_log_wrapper.c
+++ b/src/server/wlroots_log_wrapper.c
@@ -652,6 +652,11 @@ void river_wlr_keyboard_init(struct wlr_keyboard *keyboard,
 	wlr_keyboard_init(keyboard, &impl, name);
 }
 
+struct river_blur_data {
+	bool enabled;
+	bool optimized;
+};
+
 static void enable_blur_iterator(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data) {
 	(void)sx;
 	(void)sy;
@@ -659,18 +664,21 @@ static void enable_blur_iterator(struct wlr_scene_buffer *buffer, int sx, int sy
 	if (!scene_surface) {
 		return;
 	}
-	bool enabled = *(bool *)user_data;
+	struct river_blur_data *data = (struct river_blur_data *)user_data;
+	bool enabled = data->enabled;
+	bool optimized = data->optimized && enabled;
 	if (buffer->backdrop_blur != enabled ||
-		buffer->backdrop_blur_optimized != enabled ||
+		buffer->backdrop_blur_optimized != optimized ||
 		buffer->backdrop_blur_ignore_transparent != enabled) {
 		wlr_scene_buffer_set_backdrop_blur(buffer, enabled);
-		wlr_scene_buffer_set_backdrop_blur_optimized(buffer, enabled);
+		wlr_scene_buffer_set_backdrop_blur_optimized(buffer, optimized);
 		wlr_scene_buffer_set_backdrop_blur_ignore_transparent(buffer, enabled);
 	}
 }
 
-void river_scene_node_enable_blur(struct wlr_scene_node *node, bool enabled) {
-	wlr_scene_node_for_each_buffer(node, enable_blur_iterator, &enabled);
+void river_scene_node_enable_blur(struct wlr_scene_node *node, bool enabled, bool optimized) {
+	struct river_blur_data data = { .enabled = enabled, .optimized = optimized };
+	wlr_scene_node_for_each_buffer(node, enable_blur_iterator, &data);
 }
 
 static void set_opacity_iterator(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data) {
diff --git a/src/server/xdg_toplevel.rs b/src/server/xdg_toplevel.rs
index 99cbdce..bf2a48b 100644
--- a/src/server/xdg_toplevel.rs
+++ b/src/server/xdg_toplevel.rs
@@ -411,6 +411,7 @@ unsafe extern "C" fn handle_commit(listener: *mut ffi::wl_listener, _data: *mut
     ffi::river_scene_node_enable_blur(
         (*window).surfaces.tree as *mut ffi::wlr_scene_node,
         (*window).rendering_requested.blur,
+        (*(*window).server).wm.layout.scenefx_optimized_blur,
     );
 
     let capture_node = &mut (*(*window).capture_scene).tree as *mut ffi::wlr_scene_tree as *mut ffi::wlr_scene_node;
diff --git a/wrapper.h b/wrapper.h
index eb573c3..6027d53 100644
--- a/wrapper.h
+++ b/wrapper.h
@@ -257,7 +257,7 @@ struct wlr_seat_client *river_wlr_drag_get_seat_client(struct wlr_drag *drag);
 
 void river_wlr_keyboard_init(struct wlr_keyboard *keyboard, void (*led_update)(struct wlr_keyboard *keyboard, uint32_t leds), const char *name);
 
-void river_scene_node_enable_blur(struct wlr_scene_node *node, bool enabled);
+void river_scene_node_enable_blur(struct wlr_scene_node *node, bool enabled, bool optimized);
 
 void river_scene_node_set_opacity(struct wlr_scene_node *node, float opacity);