qt6-base-fourier: GL_ALPHA → GL_R8 on OpenGL ES 3.x
build and publish packages / distcc-avahi-aarch64 (push) Successful in 30s
build and publish packages / lmcp-any (push) Successful in 7s
build and publish packages / lmcp-debian (push) Successful in 5s
build and publish packages / claude-his-any (push) Successful in 8s
build and publish packages / ffmpeg-v4l2-request-aarch64 (push) Successful in 12m5s
build and publish packages / claude-his-debian (push) Successful in 4s

Three small runtime checks in qtbase 6.11.0:

1. src/opengl/qopengltextureglyphcache.cpp createTextureData() and
   load_glyph_image_to_texture() — the `#else` branch (active when
   qtbase is built with QT_CONFIG(opengles2), every aarch64 distro)
   hard-codes GL_ALPHA without checking the runtime context's ES
   version. Replace with `useR8 = ctx->format().majorVersion() >= 3`
   so ES 3+ contexts get GL_R8 + GL_RED.

2. src/gui/rhi/qrhigles2.cpp toGlTextureFormat() RED_OR_ALPHA8 case
   — gated only on caps.coreProfile. Extend with
   `caps.gles && caps.ctxMajor >= 3`.

3. src/opengl/qopengltextureuploader.cpp Format_Alpha8 and
   Format_Grayscale8 cases — short-circuit on `context->isOpenGLES()`
   before reaching the swizzle fallback. Restrict to ES 2 only so
   ES 3+ falls through to the existing TextureSwizzle path.

Discovered while validating chromium-fourier patch 3/3 (NV12
EXTERNAL_OES) on ohm. The chrome stall, VLC vout init failure and
mpv "could not initialize video chain" all share this Qt 6 root
cause: every Qt application running on Mali / panfrost / panthor
under a KWin Wayland session emits glTexImage2D(GL_ALPHA) on every
text-glyph cache upload, mesa returns GL_INVALID_VALUE, the
compositor's frame-callback path stalls, and every wayland video
client deadlocks behind it.

PKGBUILD inherits from extra/qt6-base 6.11.0-2 with arch+=aarch64,
epoch=1 to dominate Arch's pkgrel until upstream lands the fix.
qt6-base-cflags.patch and qt6-base-nostrip.patch carried verbatim
from upstream packaging.

KWIN_PIVOT.md (in chromium-fourier/) carries the full diagnosis
thread.
This commit is contained in:
2026-04-28 12:35:08 +00:00
parent cd25d02e01
commit 1dada5122b
6 changed files with 378 additions and 0 deletions
+192
View File
@@ -0,0 +1,192 @@
# Maintainer: Markus Fritsche <mfritsche@reauktion.de>
# Upstream maintainer: Antonio Rojas <arojas@archlinux.org>
# Upstream contributor: Andrea Scarpino <andrea@archlinux.org>
#
# qt6-base-fourier — Qt 6 base with the GL_TEXTURE_*_OPENGL_ES_3 fix
# unlocked. Adds three small runtime checks so that
# QOpenGLTextureGlyphCache, QRhiGles2 (RED_OR_ALPHA8 path) and
# QOpenGLTextureUploader (Format_Alpha8 / Format_Grayscale8) pick
# GL_R8 instead of GL_ALPHA when the live OpenGL context advertises
# ES 3.x or newer. Without those patches Qt 6 emits
# `glTexImage2D(internalFormat=GL_ALPHA)` on Mali-class GLES3
# hardware (mesa panfrost / panthor) — every call returns
# GL_INVALID_VALUE, every dependent glTexSubImage2D errors at level
# 0, and KWin's compositor frame-callback path stalls so badly that
# every Wayland video client deadlocks. Discovered while validating
# chromium-fourier patch 3/3 (NV12 zero-copy) on ohm (PineTab2 /
# RK3566 / hantro mainline) and the chrome+VLC+mpv stalls turned out
# to share a Qt root cause. See ../chromium-fourier/KWIN_PIVOT.md
# for the diagnosis story and the upstream-targetable patch set.
# pkgbase stays as qt6-base so $_pkgfn (= ${pkgbase/6-/} = "qtbase")
# resolves correctly. The "-fourier" suffix lives only in the
# directory name and the commit history; epoch=1 gives our local
# build strict precedence over upstream pkgrel=2 until upstream lands
# the GL_R8/ES3 fix and we can drop the epoch.
pkgbase=qt6-base
pkgname=(qt6-base
qt6-xcb-private-headers)
_pkgver=6.11.0
pkgver=${_pkgver/-/}
pkgrel=2
epoch=1
arch=(aarch64 x86_64)
url='https://www.qt.io'
license=(GPL-3.0-only
LGPL-3.0-only
LicenseRef-Qt-Commercial
Qt-GPL-exception-1.0)
pkgdesc='A cross-platform application and UI framework'
depends=(brotli
dbus
double-conversion
fontconfig
freetype2
gcc-libs
glib2
glibc
harfbuzz
icu
krb5
libb2
libcups
libdrm
libgl
libice
libinput
libjpeg-turbo
libpng
libproxy
libsm
liburing
libx11
libxcb
libxkbcommon
libxkbcommon-x11
md4c
mesa
mtdev
openssl
pcre2
shared-mime-info
sqlite
systemd-libs
tslib
wayland
xcb-util-cursor
xcb-util-image
xcb-util-keysyms
xcb-util-renderutil
xcb-util-wm
xdg-utils
zlib
zstd)
makedepends=(alsa-lib
cmake
cups
freetds
git
gst-plugins-base-libs
gtk3
jemalloc
libfbclient
libpulse
mariadb-libs
ninja
postgresql
renderdoc
unixodbc
vulkan-headers
xmlstarlet)
optdepends=('freetds: MS SQL driver'
'gdk-pixbuf2: GTK platform plugin'
'gtk3: GTK platform plugin'
'libfbclient: Firebird/iBase driver'
'mariadb-libs: MariaDB driver'
'pango: GTK platform plugin'
'perl: for syncqt'
'postgresql-libs: PostgreSQL driver'
'unixodbc: ODBC driver')
groups=(qt6)
_pkgfn=${pkgbase/6-/}
source=(git+https://code.qt.io/qt/$_pkgfn#tag=v$_pkgver
patches/qt6-base-cflags.patch
patches/qt6-base-nostrip.patch
patches/0001-qopengltextureglyphcache-pick-GL_R8-on-ES3.patch
patches/0002-qrhigles2-RED_OR_ALPHA8-pick-GL_R8-on-ES3.patch
patches/0003-qopengltextureuploader-pick-GL_R8-on-ES3.patch)
sha256sums=('2223c075e95d86f8dbf6395b025a74d996c418f094453c903290e3c2663fbed2'
'5411edbe215c24b30448fac69bd0ba7c882f545e8cf05027b2b6e2227abc5e78'
'4b93f6a79039e676a56f9d6990a324a64a36f143916065973ded89adc621e094'
'SKIP'
'SKIP'
'SKIP')
prepare() {
patch -d $_pkgfn -p1 < patches/qt6-base-cflags.patch # Use system CFLAGS
patch -d $_pkgfn -p1 < patches/qt6-base-nostrip.patch # Don't strip binaries with qmake
# cherry-pick needs git author identity; git-cli refuses without it.
git -C $_pkgfn -c user.email=fourier@build -c user.name='qt6-base-fourier build' \
cherry-pick -n 8b54513cdcf62047376a5d27d784ad68a8f235bf # Fix qdbus crashes
# qt6-base-fourier — three small runtime-checks that pick GL_R8 over
# GL_ALPHA when the live GL context is ES 3 or newer. See patches/
# for the per-site diagnosis. The chromium-fourier KWIN_PIVOT.md
# writeup carries the discovery thread.
patch -d $_pkgfn -p1 < patches/0001-qopengltextureglyphcache-pick-GL_R8-on-ES3.patch
patch -d $_pkgfn -p1 < patches/0002-qrhigles2-RED_OR_ALPHA8-pick-GL_R8-on-ES3.patch
patch -d $_pkgfn -p1 < patches/0003-qopengltextureuploader-pick-GL_R8-on-ES3.patch
}
build() {
# Set no_direct_extern_access based on architecture
if [[ $CARCH == "aarch64" || $CARCH == "riscv64" ]]; then
_no_direct_extern_access=OFF
else
_no_direct_extern_access=ON
fi
cmake -B build -S $_pkgfn -G Ninja \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DINSTALL_BINDIR=lib/qt6/bin \
-DINSTALL_PUBLICBINDIR=bin \
-DINSTALL_LIBEXECDIR=lib/qt6 \
-DINSTALL_DOCDIR=share/doc/qt6 \
-DINSTALL_ARCHDATADIR=lib/qt6 \
-DINSTALL_DATADIR=share/qt6 \
-DINSTALL_INCLUDEDIR=include/qt6 \
-DINSTALL_MKSPECSDIR=lib/qt6/mkspecs \
-DINSTALL_EXAMPLESDIR=share/doc/qt6/examples \
-DFEATURE_journald=ON \
-DFEATURE_libproxy=ON \
-DFEATURE_openssl_linked=ON \
-DFEATURE_system_sqlite=ON \
-DFEATURE_system_xcb_xinput=ON \
-DFEATURE_no_direct_extern_access=$_no_direct_extern_access \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \
-DCMAKE_MESSAGE_LOG_LEVEL=STATUS
cmake --build build
}
package_qt6-base() {
pkgdesc='A cross-platform application and UI framework'
depends+=(qt6-translations)
DESTDIR="$pkgdir" cmake --install build
install -Dm644 $_pkgfn/LICENSES/* -t "$pkgdir"/usr/share/licenses/$pkgbase
}
package_qt6-xcb-private-headers() {
pkgdesc='Private headers for Qt6 Xcb'
depends=("qt6-base=$pkgver")
optdepends=()
groups=()
cd $_pkgfn
install -d -m755 "$pkgdir"/usr/include/qt6xcb-private/gl_integrations
cp -r src/plugins/platforms/xcb/*.h "$pkgdir"/usr/include/qt6xcb-private/
cp -r src/plugins/platforms/xcb/gl_integrations/*.h "$pkgdir"/usr/include/qt6xcb-private/gl_integrations/
}