#!/bin/bash set -euo pipefail SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd)" WAYLAND_SHELL="${WAYLAND_SHELL:-xdg-shell}" CLANG_QUERY="${CLANG_QUERY:-clang-query}" BUILD_DIR="${BUILD_DIR:-$SCRIPT_DIR/client/build}" case "$WAYLAND_SHELL" in xdg-shell) shell_ignore=shell_libdecor.c ;; libdecor) shell_ignore=shell_xdg.c ;; *) echo "Unknown Wayland shell: $WAYLAND_SHELL" exit 1 esac if ! command -v "$CLANG_QUERY" &> /dev/null; then echo "clang-query is not installed" exit 1 fi if [ ! -f "$BUILD_DIR/compile_commands.json" ]; then echo "compile_commands.json not found in $BUILD_DIR" echo 'Run cmake with -DCMAKE_EXPORT_COMPILE_COMMANDS=ON to enable' exit 1 fi tempdir="$(mktemp -d)" cleanup() { rm -rf "$tempdir" } trap cleanup EXIT sed '/EGL_VERSION_1_5/,$d' /usr/include/EGL/egl.h > "$tempdir/egl1.4.h" getCalls() { query="$1" dir="$2" command=(find "$dir" -name '*.c') if [ $# -gt 2 ]; then command+=(-not) shift 2 for exclude in "$@"; do command+=(-name "$exclude") done fi cat > "$tempdir/query" <<EOF set output print set bind-root false m callExpr(callee(functionDecl(matchesName("::$query")).bind("func"))) EOF "${command[@]}" -exec "$CLANG_QUERY" -p "$BUILD_DIR/compile_commands.json" -f "$tempdir/query" {} + | \ grep -Po "(?<= )\b$query(?=\()" | sort -u } checkCalls() { name="$1" file="$2" standard="$3" while read -r func; do if ! grep -q "$func" "$file"; then echo "Found $func in $name, which is not in $standard" fails=$((fails+1)) fi done } getGLCalls() { getCalls 'gl[A-WYZ]\w*' "$@" } getEGLCalls() { getCalls 'egl[A-Z]\w*' "$@" } getGLXCalls() { getCalls 'glX\w+' "$@" } checkGLESCalls() { name="$1" shift checkCalls "$name" /usr/include/GLES3/gl3.h 'OpenGL ES 3.0' < <(getGLCalls "$@") } checkEGLCalls() { name="$1" shift checkCalls "$name" "$tempdir/egl1.4.h" 'EGL 1.4' < <(getEGLCalls "$@") } checkGLCalls() { name="$1" shift checkCalls "$name" /usr/include/GL/gl.h 'OpenGL 1.3' < <(getGLCalls "$@") } checkGLXCalls() { name="$1" shift checkCalls "$name" /usr/include/GL/glx.h 'GLX 1.3' < <(getGLXCalls "$@") } forbidCalls() { name="$1" while read -r func; do echo "Found $func in $name, which is forbidden" fails=$((fails+1)) done } forbidEGLCalls() { name="$1" shift forbidCalls "$name" < <(getEGLCalls "$@") } forbidGLXCalls() { name="$1" shift forbidCalls "$name" < <(getGLXCalls "$@") } forbidGLCalls() { name="$1" shift forbidCalls "$name" < <(getGLCalls "$@") } fails=0 checkGLESCalls 'EGL backend' client/renderers/EGL checkEGLCalls 'EGL backend' client/renderers/EGL forbidGLXCalls 'EGL backend' client/renderers/EGL checkGLCalls 'OpenGL backend' client/renderers/OpenGL forbidGLXCalls 'OpenGL backend' client/renderers/OpenGL checkGLXCalls 'X11 display server' client/displayservers/X11 forbidGLCalls 'X11 display server' client/displayservers/X11 checkEGLCalls 'Wayland display server' client/displayservers/Wayland "$shell_ignore" forbidGLCalls 'Wayland display server' client/displayservers/Wayland "$shell_ignore" forbidGLXCalls 'Wayland display server' client/displayservers/Wayland "$shell_ignore" if [ "$fails" -eq 0 ]; then echo 'All GL function calls look fine.' else echo 'Use indirection for the listed GL function calls.' exit 1 fi