diff --git a/bin/omarchy-hw-hybrid-gpu b/bin/omarchy-hw-hybrid-gpu index 13fd15cd..42f3c19d 100755 --- a/bin/omarchy-hw-hybrid-gpu +++ b/bin/omarchy-hw-hybrid-gpu @@ -2,8 +2,23 @@ # omarchy:summary=Detect whether the system has an active hybrid GPU configuration -if omarchy-cmd-present supergfxctl; then - supergfxctl -s 2>/dev/null | grep -qw Hybrid -else +multiple_gpus() { (($(lspci | grep -cE 'VGA|3D|Display') >= 2)) +} + +if omarchy-cmd-present supergfxctl; then + # A wedged supergfxd blocks its clients forever, and this gate runs while + # the menu renders. Bound the query, and treat a daemon that cannot answer + # like a machine without supergfxctl: count GPUs instead of hiding hardware + # that is really there. + modes=$(timeout --kill-after=1s 1s supergfxctl -s 2>/dev/null) + status=$? + + if ((status == 124 || status == 137)); then + multiple_gpus + else + grep -qw Hybrid <<<"$modes" + fi +else + multiple_gpus fi diff --git a/test/shell.d/hw-hybrid-gpu-test.sh b/test/shell.d/hw-hybrid-gpu-test.sh new file mode 100644 index 00000000..d7b7ae77 --- /dev/null +++ b/test/shell.d/hw-hybrid-gpu-test.sh @@ -0,0 +1,91 @@ +#!/bin/bash + +source "$(dirname "$0")/base-test.sh" + +test_tmp=$(mktemp -d) || fail "test temp directory is available" +trap 'rm -rf "$test_tmp"' EXIT + +fake_bin="$test_tmp/bin" +mkdir -p "$fake_bin" + +cat >"$fake_bin/supergfxctl" <<'STUB' +#!/bin/bash + +[[ $1 == "-s" ]] || exit 64 + +case "${BLOCKED:-no}" in +kill-only) + trap '' TERM + /usr/bin/sleep 30 + ;; +term) + /usr/bin/sleep 30 + ;; +esac + +((${FAIL_STATUS:-0})) && exit "$FAIL_STATUS" + +printf '%s\n' "${SUPPORTED_MODES:-Integrated Hybrid}" +STUB + +cat >"$fake_bin/lspci" <<'STUB' +#!/bin/bash + +for _ in $(seq "${GPU_COUNT:-1}"); do + echo "0000:00:02.0 VGA compatible controller: Stub GPU" +done +STUB + +chmod +x "$fake_bin"/* + +hybrid_gpu() { + PATH="$fake_bin:$PATH" timeout --kill-after=1s 10s bash "$ROOT/bin/omarchy-hw-hybrid-gpu" +} + +hybrid_gpu || + fail "hybrid GPU detection sees a supported Hybrid mode" +pass "hybrid GPU detection sees a supported Hybrid mode" + +SUPPORTED_MODES="Integrated Vfio" hybrid_gpu +status=$? +((status == 1)) || + fail "hybrid GPU detection trusts supergfxctl when Hybrid is unsupported" "exit status: $status" +pass "hybrid GPU detection trusts supergfxctl when Hybrid is unsupported" + +FAIL_STATUS=2 GPU_COUNT=2 hybrid_gpu +status=$? +((status == 1)) || + fail "hybrid GPU detection hides on an ordinary supergfxctl failure" "exit status: $status" +pass "hybrid GPU detection hides on an ordinary supergfxctl failure" + +BLOCKED=term GPU_COUNT=1 hybrid_gpu +status=$? +((status == 1)) || + fail "hybrid GPU detection sees one GPU as non-hybrid after a clean timeout" "exit status: $status" +pass "hybrid GPU detection sees one GPU as non-hybrid after a clean timeout" + +BLOCKED=term GPU_COUNT=2 hybrid_gpu || + fail "hybrid GPU detection counts multiple GPUs after a clean timeout" +pass "hybrid GPU detection counts multiple GPUs after a clean timeout" + +BLOCKED=kill-only GPU_COUNT=1 hybrid_gpu +status=$? +((status != 124 && status != 137)) || + fail "hybrid GPU detection stays bounded when supergfxd ignores the timeout signal" +((status == 1)) || + fail "hybrid GPU detection sees one GPU as non-hybrid when supergfxd is wedged" "exit status: $status" +pass "hybrid GPU detection stays bounded when supergfxd ignores the timeout signal" + +BLOCKED=kill-only GPU_COUNT=2 hybrid_gpu || + fail "hybrid GPU detection counts multiple GPUs when supergfxd is wedged" +pass "hybrid GPU detection counts multiple GPUs when supergfxd is wedged" + +cat >"$fake_bin/omarchy-cmd-present" <<'STUB' +#!/bin/bash +exit 1 +STUB +chmod +x "$fake_bin/omarchy-cmd-present" + +GPU_COUNT=2 hybrid_gpu || + fail "hybrid GPU detection counts GPUs without supergfxctl" +pass "hybrid GPU detection counts GPUs without supergfxctl"