From 588a3f7e36ce74702ee5679989804360a5377cc2 Mon Sep 17 00:00:00 2001 From: "Pedro M. de Echanove Pasquin" Date: Fri, 19 Jun 2026 00:04:24 +0200 Subject: [PATCH] =?UTF-8?q?Fix=20vertically-flipped=20content=20in=20the?= =?UTF-8?q?=20GLES=20path-clip=20composite=20The=20clip-layer=20composite?= =?UTF-8?q?=20shader=20sampled=20the=20offscreen=20layer=20at=20the=20wron?= =?UTF-8?q?g=20vertical=20position,=20so=20path-clipped=20content=20(e.g.?= =?UTF-8?q?=20a=20circular=20avatar)=20came=20out=20upside=20down=20on=20t?= =?UTF-8?q?he=20GLES=20backend.=20`v=5Fuv.y`=20runs=20bottom-to-top=20in?= =?UTF-8?q?=20screen=20space=20=E2=80=94=20the=20layer=20FBO=20has=20GL's?= =?UTF-8?q?=20lower-left=20origin,=20and=20`ortho=5Frect`=20plus=20the=20t?= =?UTF-8?q?exture=20shader's=20flip=20establish=20that=20`v=5Fuv.y=20=3D?= =?UTF-8?q?=3D=201`=20is=20the=20top=20edge.=20The=20composite=20computed?= =?UTF-8?q?=20the=20fragment's=20screen=20Y=20as=20`bbox.y=20+=20v=5Fuv.y?= =?UTF-8?q?=20*=20bbox.h`,=20which=20is=20the=20inverted=20Y,=20so=20it=20?= =?UTF-8?q?read=20the=20layer=20mirrored=20about=20the=20horizontal=20axis?= =?UTF-8?q?.=20Compute=20it=20as=20`bbox.y=20+=20(1=20-=20v=5Fuv.y)=20*=20?= =?UTF-8?q?bbox.h`=20instead.=20The=20mask=20sampling=20was=20already=20co?= =?UTF-8?q?rrect=20(and=20a=20symmetric=20circle=20hid=20the=20flip=20in?= =?UTF-8?q?=20the=20example;=20a=20photo=20reveals=20it).=20The=20software?= =?UTF-8?q?=20backend=20is=20unaffected=20=E2=80=94=20it=20clips=20through?= =?UTF-8?q?=20a=20coverage=20mask=20with=20no=20layer=20round-trip.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/gles_render/shaders.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gles_render/shaders.rs b/src/gles_render/shaders.rs index 5d89299..10a3704 100644 --- a/src/gles_render/shaders.rs +++ b/src/gles_render/shaders.rs @@ -163,7 +163,10 @@ uniform vec2 u_canvas; uniform vec4 u_bbox; void main() { - vec2 sp = u_bbox.xy + v_uv * u_bbox.zw; + // `v_uv.y` runs bottom-to-top in screen space (FBO origin is lower-left, as + // `ortho_rect` + the texture shader's flip establish), so the screen Y of + // this fragment is `bbox.y + (1 - v_uv.y) * bbox.h`. + vec2 sp = vec2( u_bbox.x + v_uv.x * u_bbox.z, u_bbox.y + ( 1.0 - v_uv.y ) * u_bbox.w ); vec2 luv = vec2( sp.x / u_canvas.x, 1.0 - sp.y / u_canvas.y ); vec4 col = texture2D( u_layer, luv ); float cov = texture2D( u_mask, vec2( v_uv.x, 1.0 - v_uv.y ) ).a;