Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
fix: optimized blur works for rounded windows — drop the radius opt-out
The `radius > 0 -> use_optimized = false` gate (7fd57da) assumed the
optimized blur node paints a square under the rounded standard node.
It doesn't: fx_render_pass_add_optimized_blur only re-bakes the shared
offscreen cache (read_to_buffer), and the visible shape — including
corner radii — always comes from the standard blur node's sampler,
which carries wlr_scene_blur_set_corner_radius in both modes. Since
every decorated window is rounded, the gate silently disabled
scenefx_optimized_blur DE-wide, forcing full-backdrop dual-kawase blur
per frame per translucent window (3× ~2064x2064 'optimized: 0' passes
per frame, ~66fps even at idle).
Measured downstream effect (cce-ui@a73777c / cce-system-interface@
9a8c7d3 tracers): compositor frame rate drops 66->~30fps under hover
traffic, frame-done to demand-driven clients arrives 2-7 vsyncs late
(28-99ms, growing), hover feedback lands at 4-10Hz. Layer-shell status
gates are untouched (status backdrop deliberately live-blurs the
windows beneath it).
VERIFY PENDING restart: the running session picks up the new cce-fx on
next compositor restart. Recheck with the same tracers: idle should
quiesce (no 66fps re-render loop), and hover-sweep frame-done waits
should sit at ~16ms.
Co-Authored-By: Claude Fable 5 <[email protected]>
src/server/window.rs | 23 ++++++++++++++++-------
src/server/xdg_toplevel.rs | 9 ++++++++-
2 files changed, 24 insertions(+), 8 deletions(-)
diff --git a/src/server/window.rs b/src/server/window.rs
index 97ecaf3..c840432 100644
--- a/src/server/window.rs
+++ b/src/server/window.rs
@@ -2047,12 +2047,14 @@ impl Window {
} else {
0
};
- // The optimized blur node sits UNDER the standard one and cannot be rounded
- // (wlr_scene_optimized_blur has no radius field in the vendored scenefx), so
- // for a window with rounded corners it would keep painting square corners
- // underneath a correctly rounded standard blur. Trade the optimization away
- // exactly where it would be visible, and keep it everywhere else.
- let use_optimized = if is_status || radius > 0 {
+ // Rounded corners do NOT require live blur: the corner shape is applied by the
+ // standard blur node's sampler (wlr_scene_blur_set_corner_radius) in both modes;
+ // the optimized node only re-bakes the shared offscreen cache
+ // (fx_render_pass_add_optimized_blur -> read_to_buffer) and never paints on
+ // screen. The old `radius > 0` opt-out silently disabled the optimization for
+ // every (rounded) window, forcing full-backdrop dual-kawase blur per frame per
+ // translucent window — the DE-wide hover-lag / constant-GPU-load root cause.
+ let use_optimized = if is_status {
false
} else {
(*self.server).wm.layout.scenefx_optimized_blur
@@ -2508,7 +2510,14 @@ impl Window {
} else {
0
};
- let use_optimized = if is_status || radius > 0 {
+ // Rounded corners do NOT require live blur: the corner shape is applied by the
+ // standard blur node's sampler (wlr_scene_blur_set_corner_radius) in both modes;
+ // the optimized node only re-bakes the shared offscreen cache
+ // (fx_render_pass_add_optimized_blur -> read_to_buffer) and never paints on
+ // screen. The old `radius > 0` opt-out silently disabled the optimization for
+ // every (rounded) window, forcing full-backdrop dual-kawase blur per frame per
+ // translucent window — the DE-wide hover-lag / constant-GPU-load root cause.
+ let use_optimized = if is_status {
false
} else {
(*self.server).wm.layout.scenefx_optimized_blur
diff --git a/src/server/xdg_toplevel.rs b/src/server/xdg_toplevel.rs
index 9b2a4ad..2c2fe54 100644
--- a/src/server/xdg_toplevel.rs
+++ b/src/server/xdg_toplevel.rs
@@ -604,7 +604,14 @@ unsafe extern "C" fn handle_commit(listener: *mut ffi::wl_listener, _data: *mut
} else {
crate::window::widen_corner_radius(radius, actual_w as i32, actual_h as i32)
};
- let use_optimized = if is_status || radius > 0 {
+ // Rounded corners do NOT require live blur: the corner shape is applied by the
+ // standard blur node's sampler (wlr_scene_blur_set_corner_radius) in both modes;
+ // the optimized node only re-bakes the shared offscreen cache
+ // (fx_render_pass_add_optimized_blur -> read_to_buffer) and never paints on
+ // screen. The old `radius > 0` opt-out silently disabled the optimization for
+ // every (rounded) window, forcing full-backdrop dual-kawase blur per frame per
+ // translucent window — the DE-wide hover-lag / constant-GPU-load root cause.
+ let use_optimized = if is_status {
false
} else {
(*(*window).server).wm.layout.scenefx_optimized_blur