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

commitb54d917f71d624530841794d830d44a82867fe85
parent5b464dbfa9
authorLucas Galante <[email protected]>
date2026-08-20 13:39
scenefx: per-corner radii rendered vertically mirrored — swap at upload

The corner-SDF shaders flip Y on top of an already top-down
gl_FragCoord in this renderer's FBO setup, so a radius bound to the
shader's 'top' slots rendered at the SCREEN bottom and vice versa —
for both a rect's own corners and its clipped-region cutout. Every
consumer to date used equal radii on all four corners (grid cells,
window backgrounds), which masked the mirror completely; the border
corner pieces are the first per-corner-asymmetric rects and rendered
inside-out: the outer arc at the wrong end of the L, the clip hole's
rounding on the wrong corner (a square notch at the window corner).

Fix: swap the vertical pairs in uniform_corner_radii_set, so scene
corners land where they say for every shader consuming the helper.
Verified by a distinct-radii probe (scene 40/20/10/0 measured on
screen at exactly those corners) and radially against the analytic
superellipse: handle band inner boundary on the window silhouette
(r=35, n=4.5), outer concentric at r=51, within ±2px over the sweep.

Debugging note for the future: the CURSOR SPRITE sat exactly on the
corner arc in every hover capture and read as a missing/square corner
— park the pointer away from the geometry before measuring.

Co-Authored-By: Claude Fable 5 <[email protected]>

 scenefx/render/fx_renderer/shaders.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/scenefx/render/fx_renderer/shaders.c b/scenefx/render/fx_renderer/shaders.c
index 54f1c4d..3903b6b 100644
--- a/scenefx/render/fx_renderer/shaders.c
+++ b/scenefx/render/fx_renderer/shaders.c
@@ -117,10 +117,19 @@ float fx_corner_shape(void) {
 
 void uniform_corner_radii_set(const struct shader_corner_radii *uniform,
 		const struct fx_corner_fradii *corners) {
-	glUniform1f(uniform->top_left, corners->top_left);
-	glUniform1f(uniform->top_right, corners->top_right);
-	glUniform1f(uniform->bottom_left, corners->bottom_left);
-	glUniform1f(uniform->bottom_right, corners->bottom_right);
+	/* The corner-SDF shaders flip Y (relative_pos.y = size.y - y) on top of
+	 * an already top-down gl_FragCoord in this renderer's FBO setup, so a
+	 * radius bound to the shader's "top" slots renders at the SCREEN bottom
+	 * and vice versa. Every symmetric consumer (grid cells, window
+	 * backgrounds — equal radii on all four corners) masked this for years;
+	 * the border corner pieces are the first per-corner-asymmetric rects
+	 * and rendered vertically mirrored (arc at the wrong end of the L, the
+	 * clip hole's rounding on the wrong corner). Swap the vertical pairs at
+	 * upload so scene-space corners land where they say. */
+	glUniform1f(uniform->top_left, corners->bottom_left);
+	glUniform1f(uniform->top_right, corners->bottom_right);
+	glUniform1f(uniform->bottom_left, corners->top_left);
+	glUniform1f(uniform->bottom_right, corners->top_right);
 	glUniform1f(uniform->shape, global_corner_shape);
 }
 // Shaders