I’m migrating our kiosk from X11/Openbox + Chromium kiosk to Wayland (ubuntu-frame + wpe-webkit-mir-kiosk). Functionally it launches, but I’m hitting multiple issues that look like GPU acceleration is not being used.
Issues observed
- Software rendering (llvmpipe) instead of GPU
- The renderer reports llvmpipe / software rasterizer, not Mali/Panfrost/RK GPU.
- Because of this, the UI feels sluggish (scrolling, animations, page transitions).
- Lag / high CPU usage
- CPU usage increases significantly when the web UI loads (even for normal screens).
- The experience is not smooth compared to Chromium on X11.
- EGL/GL/GPU related errors in logs
- ubuntu-frame logs show lines indicating fallback to software (mentions like EGL / GL renderer / llvmpipe).
- WPE sometimes prints EGL initialization or GPU context warnings (looks like it can’t get a proper HW EGL context).
- Kiosk stability concerns (watchdog is okay, but rendering isn’t)
- My URL-gate systemd timer successfully starts/stops WPE based on reachability,
- but since rendering is software-based, it doesn’t meet performance requirements and may cause long-term thermal/CPU load issues.
Help I need from you guys
- Confirm the correct GPU stack for our Vicharak image (RK3588) with ubuntu-frame/WPE.
- Tell me the required drivers/packages, and whether snap needs additional interfaces (ex: opengl, access to
/dev/drior mali nodes). - Any required env vars / configuration to force GPU (and avoid llvmpipe).
- If WPE is not the right option, recommend the best Wayland kiosk approach that uses GPU reliably on this board. the script
i am using now :
#!/usr/bin/env bash
set -euo pipefail
# =======================
# CONFIG (edit if needed)
# =======================
APP_URL="${APP_URL:-http://localhost:80/}"
# Optional: extra endpoints your frontend *must* be able to reach
# e.g. BACKEND_URLS="http://localhost:8084/health http://lcoalhost:8554/"
BACKEND_URLS="${BACKEND_URLS:-}"
WAIT_SECS="${WAIT_SECS:-180}" # first-time wait before enabling watchdog
CHECK_SECS="${CHECK_SECS:-5}" # watchdog interval
FRAME_BG="${FRAME_BG:-0x000000}" # black
# =======================
log(){ echo "[kiosk] $*"; }
if [[ $EUID -ne 0 ]]; then
echo "Run as root: sudo $0"
exit 1
fi
log "Install small deps"
apt-get update -y
apt-get install -y curl locales || true
locale-gen en_US.UTF-8 || true
update-locale LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 || true
log "Ensure snapd is running"
apt-get install -y snapd || true
systemctl enable --now snapd.socket || true
log "Install snaps"
snap install ubuntu-frame || true
snap install wpe-webkit-mir-kiosk || true
log "Configure ubuntu-frame (daemon + black wallpaper + hide cursor)"
snap set ubuntu-frame daemon=true || true
# ubuntu-frame accepts config items like wallpaper-top/bottom and cursor
snap set ubuntu-frame config="wallpaper-top=${FRAME_BG} wallpaper-bottom=${FRAME_BG} cursor=null" || true
log "Make sure WPE is connected to *ubuntu-frame* Wayland (NOT :wayland)"
snap disconnect wpe-webkit-mir-kiosk:wayland 2>/dev/null || true
snap connect wpe-webkit-mir-kiosk:wayland ubuntu-frame:wayland || true
log "Set WPE URL and keep it stopped until app is reachable"
snap set wpe-webkit-mir-kiosk url="$APP_URL" || true
snap set wpe-webkit-mir-kiosk daemon=false || true
snap stop wpe-webkit-mir-kiosk 2>/dev/null || true
log "Restart ubuntu-frame now (shows black background)"
snap restart ubuntu-frame || true
log "Create URL gate script (/usr/local/sbin/kiosk-url-gate.sh)"
cat >/usr/local/sbin/kiosk-url-gate.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
APP_URL="${APP_URL:-http://localhost:80/}"
BACKEND_URLS="${BACKEND_URLS:-}"
CURL_TIMEOUT="${CURL_TIMEOUT:-2}"
ok=1
check_one() {
local url="$1"
# Consider reachable if HTTP responds (2xx/3xx) quickly
curl -fsS --max-time "$CURL_TIMEOUT" "$url" >/dev/null 2>&1
}
if ! check_one "$APP_URL"; then
ok=0
else
if [[ -n "$BACKEND_URLS" ]]; then
for u in $BACKEND_URLS; do
if ! check_one "$u"; then
ok=0
break
fi
done
fi
fi
if [[ "$ok" -eq 1 ]]; then
snap start ubuntu-frame 2>/dev/null || true
snap start wpe-webkit-mir-kiosk 2>/dev/null || true
else
snap stop wpe-webkit-mir-kiosk 2>/dev/null || true
# Keep ubuntu-frame running as a black "blank screen"
snap start ubuntu-frame 2>/dev/null || true
fi
EOF
chmod +x /usr/local/sbin/kiosk-url-gate.sh
log "Create systemd service + timer (watchdog every ${CHECK_SECS}s)"
cat >/etc/systemd/system/kiosk-url-gate.service <<EOF
[Unit]
Description=Start/stop WPE kiosk based on URL reachability
After=network-online.target snapd.service
Wants=network-online.target
[Service]
Type=oneshot
Environment=APP_URL=${APP_URL}
Environment=BACKEND_URLS=${BACKEND_URLS}
Environment=CURL_TIMEOUT=2
ExecStart=/usr/local/sbin/kiosk-url-gate.sh
EOF
cat >/etc/systemd/system/kiosk-url-gate.timer <<EOF
[Unit]
Description=Run kiosk URL gate periodically
[Timer]
OnBootSec=5
OnUnitActiveSec=${CHECK_SECS}
AccuracySec=1
[Install]
WantedBy=timers.target
EOF
systemctl daemon-reload
systemctl enable --now kiosk-url-gate.timer
log "Initial wait (up to ${WAIT_SECS}s) for first successful reachability..."
end=$(( $(date +%s) + WAIT_SECS ))
while [[ $(date +%s) -lt $end ]]; do
if curl -fsS --max-time 2 "$APP_URL" >/dev/null 2>&1; then
break
fi
sleep 1
done
log "Run the gate once now"
systemctl start kiosk-url-gate.service || true
log "Status"
snap services ubuntu-frame wpe-webkit-mir-kiosk || true
systemctl status kiosk-url-gate.timer --no-pager || true
journalctl -u kiosk-url-gate.service -n 20 --no-pager || true
log "Tip: Check renderer (llvmpipe = software rendering, will be laggy)"
snap logs -n 120 ubuntu-frame | grep -E "GL renderer|llvmpipe|EGL" || true
log "Done.".
setup i was using previously : Turning Axon board into a Server + Kiosk - #25 by pawarvarun