[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 <kevin.li@cixtech.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2315>
(cherry picked from commit 2b9ce9f6c6)
(cherry picked from commit c01cf7767c)
PR: https://github.com/X11Libre/xserver/pull/3878
(cherry picked from commit e13fb91bc6)
(cherry picked from commit 17c1d7166ba0ea71072e0066c0de7d1fb1bd2eb0)
This commit is contained in:
Kevin.Li 2026-09-07 17:03:46 +08:00 • committed by Enrico Weigelt, metux IT consult
commit c0e0e3568c

View file

@ -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,