[Docs] (Anland): install MobileGL as the container's system-wide vendor and document the fallback

This commit is contained in:
2026-10-02 20:13:33 -04:00
parent 3d69c37504
commit 7a5b0755b3
5 changed files with 91 additions and 17 deletions
+28 -4
View File
@@ -23,7 +23,7 @@ nobody else is mid-test. Use your own `ct.sh` channel names (others use c, c2,
5. Container `arch-kde-mgl` (Droidspaces 6.4.5, Arch Linux ARM aarch64 glibc, host net, `rootfs.img` mounted at `/mnt/Droidspaces/arch-kde-mgl` on the Android side). Bind mounts: `/data/local/tmp/anland-mobilegl` -> `/run/anland-mobilegl`, `/data/local/tmp/display_daemon.sock` -> `/run/display.sock`.
6. `desktop-session.service` (User=swung0x48) has drop-in `ExecStart=/opt/mobilegl/bin/mobilegl-startup.sh plasma`, which writes a user drop-in for `plasma-kwin_wayland.service` (kwin_wayland_wrapper -> `/opt/mobilegl/kwin/bin/kwin_wayland` + `/opt/mobilegl/kwin/lib/libkwin.so.6.7.4`, `ANLAND_MOBILEGL=1`, `MOBILEGL_IPC_SURFACE=server`) and runs `startplasma-wayland`.
7. KWin 6.7.4 with anland's `anland` backend renders straight into the anland Android Surface through the server. Every other GL process is `MOBILEGL_IPC_SURFACE=offscreen` and presents through KWin.
8. Client = `/opt/mobilegl/lib/libMobileGL.so` (glibc aarch64): glvnd EGL vendor (`/opt/mobilegl/share/glvnd/egl_vendor.d/50_mobilegl.json`), GLX vendor (`/usr/lib/libGLX_mobilegl.so.0`, `__GLX_VENDOR_LIBRARY_NAME=mobilegl`), env `MOBILEGL_TRANSPORT=spawn MOBILEGL_IPC_DATA=shm MOBILEGL_IPC_CONTROL=unix:@anland-mobilegl`.
8. Client = `/opt/mobilegl/lib/libMobileGL.so` (glibc aarch64), the container's **system-wide** GL vendor (section below): glvnd EGL vendor `/usr/share/glvnd/egl_vendor.d/10_mobilegl.json` (sorts before the distribution's `50_*.json`, which serves whenever MobileGL declines), GLX vendor `/usr/lib/libGLX_mobilegl.so.0`, settings from `/etc/mobilegl/client.conf` (`MOBILEGL_TRANSPORT=spawn MOBILEGL_IPC_DATA=shm MOBILEGL_IPC_CONTROL=unix:@anland-mobilegl`) + `/etc/mobilegl/backend`. No per-process environment is needed.
9. Zero-copy windows: client `wl_egl_window` frames are server-allocated AHardwareBuffer "shared images" exported as dma-buf fds over `zwp_linux_dmabuf_v1`; KWin imports them with EGL and the server recognises its own buffer by inode. KWin gets a DRM device via `GBM_BACKEND=mobilegl` -> `/usr/lib/gbm/mobilegl_gbm.so` (node is only an identity, never ioctl'd). Without linux-dmabuf the client falls back to wl_shm readback.
10. X11 apps (Xwayland) use the MobileGL GLX vendor with per-frame readback + `xcb_put_image`. Chrome runs ANGLE-GLES over MobileGL EGL with the GPU in-process (`mobilegl-startup.sh chrome`).
@@ -69,7 +69,7 @@ bash scripts/cyc.sh s1 # clear sticky SW-renderer key, push, swa
**Client + GBM backend (container glibc) via WSL cross-build**
```sh
bash scripts/xbuild.sh [--reconfigure] # WSL ~/mgl-xbuild-a64; ~150 s full, seconds incremental
bash scripts/xdeploy.sh # rename-into-place install of libMobileGL.so + mobilegl_gbm.so, aliases, vendor JSON
bash scripts/xdeploy.sh # rename-into-place install of libMobileGL.so + mobilegl_gbm.so, aliases, vendor JSONs, client.conf, GLX/GBM env drop-ins
```
Running clients keep the old inode; restart the client, or `run-plasma.sh` for KWin/plasmashell. Build server and client from the **same commit** (both stamp `git rev-parse HEAD`), else the logs WARN "compatible wire with different build". Fallback in-container build (slow): `scripts/sync-src.sh` + anland `mobilegl-tools/anland-build-client.sh`.
@@ -92,9 +92,31 @@ MSYS2_ARG_CONV_EXCL='*' wsl -d archlinux -- bash -lc 'cd ~/mgl-anl-bld && ctest
`adb shell 'su -c "sh /data/local/tmp/anl/switch.sh DirectGLES"'` (sets the prop, writes `/etc/mobilegl/backend`, restarts the app), then `run-plasma.sh` - the running session's clients are pinned to the old backend. `cyc.sh` keeps whatever is set.
## System-wide vendor and fallback
Installed by `xdeploy.sh` (and anland's `anland-build-client.sh`), so any process in the container gets MobileGL through the stock libglvnd/libgbm:
| File | Does |
|---|---|
| `/usr/share/glvnd/egl_vendor.d/10_mobilegl.json` | EGL vendor, asked before the system's `50_*.json` |
| `/opt/mobilegl/share/glvnd/egl_vendor.d/50_mobilegl.json` | same JSON, for per-process forcing with `__EGL_VENDOR_LIBRARY_FILENAMES` |
| `/etc/mobilegl/client.conf` | `KEY=value` defaults for every client (transport, data, endpoint); rewritten on deploy |
| `/etc/mobilegl/backend` | the backend (`switch.sh` writes it); wins over a `MOBILEGL_BACKEND_TYPE` line in client.conf |
| `/etc/environment.d/10-mobilegl.conf` | `__GLX_VENDOR_LIBRARY_NAME=mobilegl`, `GBM_BACKEND=mobilegl` for the systemd user manager (all Plasma services and what they start, terminals included) |
| `/etc/profile.d/mobilegl.sh` | the same two for login shells (`bash -l`, `su -l`, ssh, `droidspaces run bash -l`) |
Precedence is environment > `/etc/mobilegl/backend` (backend only) > client.conf > built-in; `MOBILEGL_CONFIG_FILE` / `MOBILEGL_BACKEND_FILE` name other files (empty = off); a server process never reads them.
**Fallback.** Before bringing anything up the client probes the configured endpoint (one non-blocking connect, `MOBILEGL_IPC_PROBE_TIMEOUT_MS`, default 250, 0 = off; a refused abstract socket answers in ~0.2 ms). With no server: the EGL vendor returns `EGL_NO_DISPLAY` and no devices (glvnd moves on to the other vendor), the GLX vendor fails `__glx_Main` (libGLX falls back to the vendor Xwayland names), and `mobilegl_gbm` fails `create_device` (libgbm falls back to the device's own backend). Client queries (`eglQueryString(EGL_NO_DISPLAY)`, `eglGetProcAddress`) never bring a session up. MobileGL also steps aside for a GBM device another backend created and for `LIBGL_ALWAYS_SOFTWARE=1` - that is how Xwayland (KWin's patch sets it) keeps the software stack. Show it without stopping the real server:
```sh
sed 's|^MOBILEGL_IPC_CONTROL=.*|MOBILEGL_IPC_CONTROL=unix:@nobody|' /etc/mobilegl/client.conf > /tmp/down.conf
sudo -u swung0x48 env -i HOME=/home/swung0x48 PATH=/usr/bin XDG_RUNTIME_DIR=/run/user/1000 WAYLAND_DISPLAY=wayland-0 \
MOBILEGL_CONFIG_FILE=/tmp/down.conf eglinfo -B -p wayland # vendor = the other one, ~0.1 s
```
## Test clients and how to verify
Inside the container as root (`printf '...' | bash scripts/ct.sh <chan>`), `mgrun offscreen <cmd>` runs a client as swung0x48 in the live session (log `/tmp/mgl-run.client.log`, override base with `MGLOG=/tmp/x.log`):
Inside the container as root (`printf '...' | bash scripts/ct.sh <chan>`), `mgrun offscreen <cmd>` runs a client as swung0x48 in the live session through a login shell, with nothing but the surface mode and the log path set (log `/tmp/mgl-run.client.log`, override base with `MGLOG=/tmp/x.log`); a plain `env -i ... bash -l -c '<cmd>'` as swung0x48 gets MobileGL the same way:
```sh
mgrun offscreen eglinfo -B ; mgrun offscreen glxinfo -B
timeout 25 mgrun offscreen glmark2-es2-wayland -s 1280x720 --run-forever > /tmp/gm.out 2>&1 &
@@ -138,7 +160,9 @@ Reference (glmark2-es2-wayland 1280x720, zero-copy vs wl_shm): Espryt 187 vs 49,
- **Input**: plain `adb shell input` is blocked - use `su -c input`; anland grabs the touchscreen, so if `input tap` does nothing use `input mouse tap x y`. Never `debuggerd -b` a container process (signal 35 kills glibc processes).
- **linux-dmabuf**: the client must use `create` + roundtrip, never `create_immed` (KWin answers a failed immediate import with a protocol error that kills the client).
- **Cross-session bugs**: noise / another window's pixels after some client starts or exits = process-global state in the multi-session server (handles are per client, FBO/VAO per context). Repro with `kscreenlocker_greet --testing`.
- `/etc/environment` leaks Mesa/KGSL variables through pam_env; `mobilegl-startup.sh` unsets them - keep that when editing it.
- `/etc/environment` leaks the baseline session's driver variables through pam_env (and, via `/usr/lib/environment.d/99-environment.conf`, into the user manager); `mobilegl-startup.sh` unsets them - keep that when editing it.
- **Shared log path**: Xwayland inherits KWin's `MOBILEGL_LOG_FILE_PATH`; any line a process logs opens (truncates) that file. MobileGL stays silent in processes it does not serve, but give any extra client its own `MOBILEGL_LOG_FILE_PATH`.
- **Stale per-process overrides**: an `__EGL_VENDOR_LIBRARY_FILENAMES` / `MOBILEGL_*` left in a unit drop-in or the user manager's environment (`systemctl --user show-environment`) still wins over the system files; `run-plasma.sh` (terminate-user) clears the manager's.
- `handoff` mentions a `kwin_wayland` logging shim and `/tmp/mgl-kwin-<pid>.log`: stale - `/opt/mobilegl/kwin/bin/kwin_wayland` is now the real binary and logs to `/tmp/mobilegl-compositor.client.log`.
## House rules
@@ -2,7 +2,8 @@
# chrome-launch.sh <tag> [extra chrome flags...] - (re)start Chrome inside the running Plasma session
# through mobilegl-startup.sh's `chrome` mode (ANGLE GLES over MobileGL EGL, in-process GPU), client
# log /tmp/mgl-chrome-<tag>.client.log, then print its "presented through" line and save a screenshot
# to $ANL_DIR/ch-<tag>.png. Kills the running chrome first (pkill -x, never -f).
# to $ANL_DIR/ch-<tag>.png. Kills the running chrome first (pkill -x, never -f). MobileGL is the
# container's system-wide vendor (10_mobilegl.json + /etc/mobilegl/client.conf), so only the log is set here.
# Env: WAIT (s before checking, default 20), CHANNEL (ct.sh channel, default chrome).
set -euo pipefail
here=$(cd "$(dirname "$0")" && pwd)
@@ -11,7 +12,7 @@ TAG=${1:?usage: chrome-launch.sh <tag> [chrome flags...]}; shift
bash "$here/ct.sh" "${CHANNEL:-chrome}" <<IN
pkill -x chrome; sleep 2
U=\$(id -u $MGL_DESKTOP_USER)
sudo -u $MGL_DESKTOP_USER env XDG_RUNTIME_DIR=/run/user/\$U WAYLAND_DISPLAY=wayland-0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/\$U/bus __EGL_VENDOR_LIBRARY_FILENAMES=/opt/mobilegl/share/glvnd/egl_vendor.d/50_mobilegl.json MOBILEGL_TRANSPORT=spawn MOBILEGL_IPC_DATA=shm MOBILEGL_ENDPOINT=unix:@anland-mobilegl MOBILEGL_BACKEND_TYPE=\$(cat /etc/mobilegl/backend) MOBILEGL_LOG_FILE_PATH=/tmp/mgl-chrome-$TAG.log bash -c 'nohup /opt/mobilegl/bin/mobilegl-startup.sh chrome --restore-last-session $* > /tmp/chrome-$TAG-out.log 2>&1 &'
sudo -u $MGL_DESKTOP_USER env XDG_RUNTIME_DIR=/run/user/\$U WAYLAND_DISPLAY=wayland-0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/\$U/bus MOBILEGL_LOG_FILE_PATH=/tmp/mgl-chrome-$TAG.log bash -c 'nohup /opt/mobilegl/bin/mobilegl-startup.sh chrome --restore-last-session $* > /tmp/chrome-$TAG-out.log 2>&1 &'
sleep ${WAIT:-20}
grep -ah 'presented through' /tmp/mgl-chrome-$TAG.client.log | head -3
IN
@@ -4,7 +4,10 @@
# mgrun offscreen glmark2-es2-wayland -s 1280x720 # Wayland client, presents through KWin
# mgrun offscreen eglinfo -B ; mgrun offscreen glxinfo -B # glxinfo goes through Xwayland + GLX vendor
# "server" is only for a client that owns the Android Surface itself (KWin does); everything else is
# offscreen. Backend = /etc/mobilegl/backend (must match the server). Client log:
# offscreen. MobileGL is the container's system-wide vendor, so nothing selects it here: EGL comes from
# /usr/share/glvnd/egl_vendor.d/10_mobilegl.json, transport/endpoint from /etc/mobilegl/client.conf,
# the backend from /etc/mobilegl/backend (must match the server), and the GLX vendor name / GBM backend
# from /etc/profile.d/mobilegl.sh (sourced by the login shell below). Client log:
# ${MGLOG:-/tmp/mgl-run.log} -> the library writes /tmp/mgl-run.client.log (truncated per run; give
# concurrent clients different MGLOG values). Env: MGLOG, DESKTOP_USER (swung0x48).
S=$1; shift
@@ -14,8 +17,5 @@ cd /tmp
exec sudo -u "$DU" env XDG_RUNTIME_DIR=/run/user/$U WAYLAND_DISPLAY=wayland-0 DISPLAY=:0 \
XAUTHORITY=$(ls /run/user/$U/xauth_* 2>/dev/null | head -1) \
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$U/bus QT_QPA_PLATFORM=wayland \
__EGL_VENDOR_LIBRARY_FILENAMES=/opt/mobilegl/share/glvnd/egl_vendor.d/50_mobilegl.json \
__GLX_VENDOR_LIBRARY_NAME=mobilegl \
MOBILEGL_TRANSPORT=spawn MOBILEGL_IPC_DATA=shm MOBILEGL_IPC_CONTROL=unix:@anland-mobilegl \
MOBILEGL_IPC_SURFACE=$S MOBILEGL_BACKEND_TYPE=$(cat /etc/mobilegl/backend 2>/dev/null || echo DirectGLES) \
MOBILEGL_LOG_FILE_PATH=${MGLOG:-/tmp/mgl-run.log} "$@"
MOBILEGL_IPC_SURFACE=$S MOBILEGL_LOG_FILE_PATH=${MGLOG:-/tmp/mgl-run.log} \
bash -lc 'exec "$@"' mgrun "$@"
@@ -2,7 +2,8 @@
# xdeploy.sh - install the WSL cross-built libMobileGL.so + mobilegl_gbm.so into the container, exactly
# like anland's anland-build-client.sh: copy to a NEW inode and rename into place (overwriting a mapped
# .so in place crashes every running client, KWin included), refresh the libEGL/libGL aliases, the
# glvnd GLX vendor link and the EGL vendor JSON. Does not restart anything: already-running clients
# glvnd GLX vendor link, the EGL vendor JSON (system-wide 10_mobilegl.json + the /opt copy), the client
# config /etc/mobilegl/client.conf and the GLX/GBM selection drop-ins. Does not restart anything: already-running clients
# keep the old inode; restart the client (or the session) to pick up the new library.
# Env: MGL_XBUILD_DIR (WSL build dir), CHANNEL (ct.sh channel, default xd), WSL_DISTRO.
set -euo pipefail
@@ -30,11 +31,35 @@ cp "$in/libMobileGL.so" /opt/mobilegl/lib/libMobileGL.so.new
mv -f /opt/mobilegl/lib/libMobileGL.so.new /opt/mobilegl/lib/libMobileGL.so
for lib in libEGL.so libEGL.so.1 libGL.so libGL.so.1; do ln -sf libMobileGL.so "/opt/mobilegl/lib/$lib"; done
ln -sf /opt/mobilegl/lib/libMobileGL.so /usr/lib/libGLX_mobilegl.so.0
printf '%s\n' '{"file_format_version":"1.0.0","ICD":{"library_path":"/opt/mobilegl/lib/libMobileGL.so"}}' >/opt/mobilegl/share/glvnd/egl_vendor.d/50_mobilegl.json
vendor='{"file_format_version":"1.0.0","ICD":{"library_path":"/opt/mobilegl/lib/libMobileGL.so"}}'
# Per-process forcing (__EGL_VENDOR_LIBRARY_FILENAMES=<this file>) keeps working off the /opt copy.
printf '%s\n' "$vendor" >/opt/mobilegl/share/glvnd/egl_vendor.d/50_mobilegl.json
# System-wide vendor: 10_ sorts ahead of the system's 50_mesa.json, so stock libglvnd asks MobileGL
# first and moves on to the other vendor whenever MobileGL declines (no server reachable).
mkdir -p /usr/share/glvnd/egl_vendor.d
printf '%s\n' "$vendor" >/usr/share/glvnd/egl_vendor.d/10_mobilegl.json.new
mv -f /usr/share/glvnd/egl_vendor.d/10_mobilegl.json.new /usr/share/glvnd/egl_vendor.d/10_mobilegl.json
# Client settings every process reads when its environment does not say otherwise (the backend
# comes from /etc/mobilegl/backend, which switch.sh rewrites).
mkdir -p /etc/mobilegl
cat >/etc/mobilegl/client.conf <<'CONF'
# MobileGL client configuration, read by every process that loads libMobileGL.so.
# KEY=value lines; a MOBILEGL_* variable in a process's environment overrides the line here.
# The backend is /etc/mobilegl/backend. Written by xdeploy.sh / anland-build-client.sh.
MOBILEGL_TRANSPORT=spawn
MOBILEGL_IPC_DATA=shm
MOBILEGL_IPC_CONTROL=unix:@anland-mobilegl
CONF
# What glvnd's libGLX and libgbm cannot infer: environment.d reaches the systemd user manager (every
# Plasma service and what it launches, terminals included), profile.d reaches login shells.
mkdir -p /etc/environment.d /etc/profile.d
printf '%s\n' '__GLX_VENDOR_LIBRARY_NAME=mobilegl' 'GBM_BACKEND=mobilegl' >/etc/environment.d/10-mobilegl.conf
printf '%s\n' 'export __GLX_VENDOR_LIBRARY_NAME=mobilegl' 'export GBM_BACKEND=mobilegl' >/etc/profile.d/mobilegl.sh
mkdir -p /usr/lib/gbm
cp "$in/mobilegl_gbm.so" /usr/lib/gbm/mobilegl_gbm.so.new
mv -f /usr/lib/gbm/mobilegl_gbm.so.new /usr/lib/gbm/mobilegl_gbm.so
rm -f "$in/libMobileGL.so" "$in/mobilegl_gbm.so"
sha256sum /opt/mobilegl/lib/libMobileGL.so /usr/lib/gbm/mobilegl_gbm.so
ls /usr/share/glvnd/egl_vendor.d/ /etc/mobilegl/ /etc/environment.d/
echo DEPLOYED
IN
@@ -13,7 +13,7 @@
- **容器** `arch-kde-mgl`:Droidspaces 6.4.5,Arch Linux ARM(aarch64 glibc),host 网络;Android 侧 `rootfs.img` 挂在 `/mnt/Droidspaces/arch-kde-mgl`。bind mount:`/data/local/tmp/anland-mobilegl` → `/run/anland-mobilegl`,`/data/local/tmp/display_daemon.sock` → `/run/display.sock`。
- **会话**:`desktop-session.service`(User=swung0x48)的 drop-in 把 ExecStart 换成 `/opt/mobilegl/bin/mobilegl-startup.sh plasma`;它每次写 `plasma-kwin_wayland.service` 的用户 drop-in(经 `kwin_wayland_wrapper` 起 `/opt/mobilegl/kwin/bin/kwin_wayland` + `/opt/mobilegl/kwin/lib/libkwin.so.6.7.4`,`ANLAND_MOBILEGL=1`、`MOBILEGL_IPC_SURFACE=server`),然后 `startplasma-wayland`。
- **KWin 6.7.4** 带 anland 的 `anland` 后端,经 server 直接画进 anland 的 Android Surface。其余 GL 进程都是 `MOBILEGL_IPC_SURFACE=offscreen`,经 KWin 合成上屏。
- **client 库** `/opt/mobilegl/lib/libMobileGL.so`(glibc aarch64):glvnd 的 EGL vendor(`/opt/mobilegl/share/glvnd/egl_vendor.d/50_mobilegl.json`)+ GLX vendor(`/usr/lib/libGLX_mobilegl.so.0`,`__GLX_VENDOR_LIBRARY_NAME=mobilegl`);环境 `MOBILEGL_TRANSPORT=spawn MOBILEGL_IPC_DATA=shm MOBILEGL_IPC_CONTROL=unix:@anland-mobilegl`。
- **client 库** `/opt/mobilegl/lib/libMobileGL.so`(glibc aarch64),是容器里**全系统**的 GL vendor(见下节):EGL vendor `/usr/share/glvnd/egl_vendor.d/10_mobilegl.json`(排在发行版的 `50_*.json` 前面,MobileGL 拒绝时由它接手)、GLX vendor `/usr/lib/libGLX_mobilegl.so.0`,配置来自 `/etc/mobilegl/client.conf`(`MOBILEGL_TRANSPORT=spawn MOBILEGL_IPC_DATA=shm MOBILEGL_IPC_CONTROL=unix:@anland-mobilegl`)+ `/etc/mobilegl/backend`。进程不需要任何专门的环境变量。
- **零拷贝窗口**:client 的 `wl_egl_window` 帧是 server 分配的 AHardwareBuffer(shared image),以 dma-buf fd 经 `zwp_linux_dmabuf_v1` 交给 KWin;KWin 用 EGL 导入,server 按 inode 认出是自己发出的那块。KWin 的 DRM 设备来自 `GBM_BACKEND=mobilegl` → `/usr/lib/gbm/mobilegl_gbm.so`(节点只当身份,从不 ioctl)。没有 linux-dmabuf 时退回 wl_shm 回读。
- **X11**(Xwayland)走 MobileGL 的 GLX vendor,每帧回读 + `xcb_put_image`。Chrome 用 `mobilegl-startup.sh chrome`:ANGLE GLES 跑在 MobileGL EGL 上,GPU 在浏览器进程内。
@@ -61,7 +61,7 @@ bash scripts/cyc.sh s1 # 删粘滞软件渲染键 → 推库 → 换
```sh
bash scripts/xbuild.sh [--reconfigure] # WSL ~/mgl-xbuild-a64;全量约 150 秒,增量几秒
bash scripts/xdeploy.sh # 新 inode 改名就位安装 libMobileGL.so + mobilegl_gbm.so,刷新别名、GLX 链接、vendor JSON
bash scripts/xdeploy.sh # 新 inode 改名就位安装 libMobileGL.so + mobilegl_gbm.so,刷新别名、GLX 链接、vendor JSON、client.conf 和 GLX/GBM 环境 drop-in
```
已经在跑的 client 继续映射旧 inode:重启那个 client,KWin / plasmashell 就 `run-plasma.sh`。server 与 client **同一个 commit** 构建(两边 stamp 都取 `git rev-parse HEAD`),否则日志里 WARN "compatible wire with different build"。容器内构建是备用路径(慢):`scripts/sync-src.sh` 同步改动的文件,再在容器里跑 anland 的 `mobilegl-tools/anland-build-client.sh`。
@@ -91,6 +91,28 @@ MSYS2_ARG_CONV_EXCL='*' wsl -d archlinux -- bash -lc 'cd ~/mgl-anl-bld && ctest
`adb shell 'su -c "sh /data/local/tmp/anl/switch.sh DirectGLES"'`(设属性、写 `/etc/mobilegl/backend`、重启 app),然后 `run-plasma.sh`——正在跑的会话里各 client 还钉在旧后端上。`cyc.sh` 不改后端。
## 全系统 vendor 与回退
`xdeploy.sh`(以及 anland 的 `anland-build-client.sh`)安装下面这些,容器里任何进程经原版 libglvnd / libgbm 就用上 MobileGL:
| 文件 | 作用 |
|---|---|
| `/usr/share/glvnd/egl_vendor.d/10_mobilegl.json` | EGL vendor,先于系统的 `50_*.json` 被问 |
| `/opt/mobilegl/share/glvnd/egl_vendor.d/50_mobilegl.json` | 同一份 JSON,留给 `__EGL_VENDOR_LIBRARY_FILENAMES` 单进程强制 |
| `/etc/mobilegl/client.conf` | 所有 client 的 `KEY=value` 默认值(transport、data、endpoint),每次部署重写 |
| `/etc/mobilegl/backend` | 后端(`switch.sh` 写);比 client.conf 里的 `MOBILEGL_BACKEND_TYPE` 优先 |
| `/etc/environment.d/10-mobilegl.conf` | `__GLX_VENDOR_LIBRARY_NAME=mobilegl`、`GBM_BACKEND=mobilegl`,给 systemd 用户管理器(所有 Plasma 服务及其子进程,包括终端) |
| `/etc/profile.d/mobilegl.sh` | 同样两项,给登录 shell(`bash -l`、`su -l`、ssh、`droidspaces run bash -l`) |
优先级:环境变量 > `/etc/mobilegl/backend`(只管后端)> client.conf > 内置默认;`MOBILEGL_CONFIG_FILE` / `MOBILEGL_BACKEND_FILE` 可指向别的文件(设为空即关闭);server 进程不读这些文件。
**回退**:真正拉起之前 client 先探一次配置的 endpoint(一次非阻塞 connect,`MOBILEGL_IPC_PROBE_TIMEOUT_MS` 默认 250,0 关闭;被拒的抽象 socket 约 0.2 ms 就有结果)。没有 server 时:EGL vendor 返回 `EGL_NO_DISPLAY`、设备数 0(glvnd 换下一个 vendor),GLX vendor 的 `__glx_Main` 失败(libGLX 回退到 Xwayland 报的 vendor),`mobilegl_gbm` 的 `create_device` 失败(libgbm 回退到设备自己的后端)。客户端查询(`eglQueryString(EGL_NO_DISPLAY)`、`eglGetProcAddress`)从不拉起会话。对别的后端创建的 GBM 设备和 `LIBGL_ALWAYS_SOFTWARE=1` 的进程,MobileGL 同样让开——Xwayland(KWin 补丁给它设了这个)因此继续走软件栈。不停真 server 的演示:
```sh
sed 's|^MOBILEGL_IPC_CONTROL=.*|MOBILEGL_IPC_CONTROL=unix:@nobody|' /etc/mobilegl/client.conf > /tmp/down.conf
sudo -u swung0x48 env -i HOME=/home/swung0x48 PATH=/usr/bin XDG_RUNTIME_DIR=/run/user/1000 WAYLAND_DISPLAY=wayland-0 \
MOBILEGL_CONFIG_FILE=/tmp/down.conf eglinfo -B -p wayland # vendor 变成另一个,约 0.1 s
```
## 跑测试 client 与验证
在容器里以 root 执行(`printf '...' | bash scripts/ct.sh <通道>`),`mgrun offscreen <命令>` 以 swung0x48 身份在当前会话里起一个 client(日志 `/tmp/mgl-run.client.log`,`MGLOG=/tmp/x.log` 可换):
@@ -140,7 +162,9 @@ Chrome:`bash scripts/chrome-launch.sh <tag> [参数]`(日志 `/tmp/mgl-chrom
- **输入注入**:普通 `adb shell input` 被拦,要 `su -c input`;anland 抓了触摸屏,`input tap` 无效时用 `input mouse tap x y`。不要对容器进程用 `debuggerd -b`(信号 35 会直接杀掉 glibc 进程)。
- **linux-dmabuf**:client 必须 `create` + roundtrip,不能 `create_immed`(KWin 对失败的立即导入回协议错误,直接断开 client)。
- **跨会话 bug**:某个 client 起来或退出后出现噪点 / 别的窗口的残影,先怀疑多会话 server 里的进程级状态(handle 是每 client 各自的,FBO / VAO 是每 context 的)。复现用 `kscreenlocker_greet --testing`。
- `/etc/environment` 经 pam_env 带进 Mesa / KGSL 变量,`mobilegl-startup.sh` 里把它们 unset 了,改脚本时保留。
- `/etc/environment` 经 pam_env(以及 `/usr/lib/environment.d/99-environment.conf` 进用户管理器)带进基线会话的驱动变量,`mobilegl-startup.sh` 里把它们 unset 了,改脚本时保留。
- **共用日志路径**:Xwayland 继承 KWin 的 `MOBILEGL_LOG_FILE_PATH`,进程写第一行日志就会打开(截断)那个文件。MobileGL 在不服务的进程里不写日志,但额外起的 client 要给自己的 `MOBILEGL_LOG_FILE_PATH`。
- **残留的单进程覆盖**:unit drop-in 或用户管理器环境(`systemctl --user show-environment`)里遗留的 `__EGL_VENDOR_LIBRARY_FILENAMES` / `MOBILEGL_*` 仍比系统文件优先;`run-plasma.sh`(terminate-user)会清掉管理器里的。
- handoff 里提到的 `kwin_wayland` 日志 shim 与 `/tmp/mgl-kwin-<pid>.log` 已过时:`/opt/mobilegl/kwin/bin/kwin_wayland` 现在就是真二进制,KWin 的 client 日志在 `/tmp/mobilegl-compositor.client.log`。
## 规矩