From 5e5fbd64b7b493d4044c99e9e97f873c5456586b Mon Sep 17 00:00:00 2001 From: "Kevin.Li" Date: Mon, 7 Sep 2026 17:03:46 +0800 Subject: [PATCH] [PR #3878] glamor: use highp for fill_pos UVs on GLES Problem: On a 2K (e.g. 2560x1440) display, WPS Office for Linux (Qt) shows corrupted text and broken vertical lines on the right side of a maximized window when the UI is updated by mouse movement (e.g. hover/scroll refreshing labels). The same controls on the left side are fine. The issue does not appear at 1080p, without glamor, or when using desktop OpenGL shaders (non-GLES). Root cause: Xwayland GBM n-buffering CopyArea's window pixmap into the present pixmap via glamor_copy (FBO texture blit). UVs are computed as (offset + pixel) * (1/width, 1/height). GLES fragment shaders default to mediump (~10-bit relative precision), so on wide pixmaps UVs near the right edge can be off by about a pixel; with GL_NEAREST this shows as shifted/broken glyphs and edges. Desktop OpenGL has no default mediump precision qualifier, so the same shader path is fine. Fix: Force highp only on fillpos uniforms/ins/outs. Keep the global mediump default for other fragment math. Change-Id: If747516bdf787e0383b42e3579acfeab30a7cb1c Signed-off-by: Kevin.Li Part-of: (cherry picked from commit 2b9ce9f6c67a3fca5720b5e7c8966365e62d96f7) (cherry picked from commit c01cf7767ce7c9cc9ca266316e277a7b0faa2fa2) PR: https://github.com/X11Libre/xserver/pull/3878 (cherry picked from commit e13fb91bc64b5a44d644975c1785cfda78c8798a) (cherry picked from commit 17c1d7166ba0ea71072e0066c0de7d1fb1bd2eb0) --- glamor/glamor_program.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/glamor/glamor_program.c b/glamor/glamor_program.c index 5cd3c59ded..5139e4517f 100644 --- a/glamor/glamor_program.c +++ b/glamor/glamor_program.c @@ -118,12 +118,36 @@ static glamor_location_var location_vars[] = { .location = glamor_program_location_fillsamp, .fs_vars = "uniform sampler2D sampler;\n" }, + /* + * fill_pos selects texels via (offset + pixel) * (1/width, 1/height). + * + * On GLES, GLAMOR_DEFAULT_PRECISION sets mediump float in the fragment + * shader. mediump typically has only ~10 bits of relative precision, so + * for large destinations (e.g. 2560px wide) UVs near the right edge can + * be off by about a pixel. With GL_NEAREST sampling that shows up as + * shifted or broken edges in CopyArea / texture-fill paths (including + * Xwayland n-buffer blits). + * + * Keep the global mediump default for other FS math; only force highp + * for these UV uniforms/ins/outs so pixel-exact sampling stays correct + * without paying highp everywhere. + */ { .location = glamor_program_location_fillpos, - .vs_vars = ("uniform vec2 fill_offset;\n" + .vs_vars = ("#ifdef GL_ES\n" + "uniform highp vec2 fill_offset;\n" + "uniform highp vec2 fill_size_inv;\n" + "out highp vec2 fill_pos;\n" + "#else\n" + "uniform vec2 fill_offset;\n" "uniform vec2 fill_size_inv;\n" - "out vec2 fill_pos;\n"), - .fs_vars = ("in vec2 fill_pos;\n") + "out vec2 fill_pos;\n" + "#endif\n"), + .fs_vars = ("#ifdef GL_ES\n" + "in highp vec2 fill_pos;\n" + "#else\n" + "in vec2 fill_pos;\n" + "#endif\n") }, { .location = glamor_program_location_font,