Skip to content

Commit 2634ccd

Browse files
committed
fix(display): make eglinfo pipeline detection work across base/prop and cache renderer classification
Accept WAYLAND_DISPLAY as either name-only (with XDG_RUNTIME_DIR) or absolute socket path (/run/wayland-0, /dev/socket/weston*). Pick a working eglinfo platform deterministically and cache EGLI_LAST_* values for consistent decisions. Signed-off-by: Srikanth Muppandam <smuppand@qti.qualcomm.com>
1 parent b6254c1 commit 2634ccd

1 file changed

Lines changed: 153 additions & 113 deletions

File tree

Runner/utils/lib_display.sh

Lines changed: 153 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,19 @@
55
# DRM display + Weston + Wayland helpers
66
# (assumes log_info/log_warn/log_error and run_with_timeout from functestlib.sh)
77
###############################################################################
8-
98
###############################################################################
109
# Internal helpers
1110
###############################################################################
11+
# These are intentional cache outputs used by callers after display_print_eglinfo_pipeline().
12+
# ShellCheck cannot always see cross-file/global usage.
13+
# shellcheck disable=SC2034
14+
EGLI_LAST_PLATFORM=""
15+
EGLI_LAST_DRIVER=""
16+
EGLI_LAST_GL_VENDOR=""
17+
EGLI_LAST_GL_RENDERER=""
18+
EGLI_LAST_PIPE_KIND=""
19+
EGLI_LAST_OUT=""
20+
1221
debugfs_is_mounted() {
1322
awk '$3=="debugfs" && $2=="/sys/kernel/debug" {found=1} END{exit(found?0:1)}' /proc/mounts 2>/dev/null
1423
}
@@ -1062,6 +1071,66 @@ egli_pick_platform_flag() {
10621071
return 0
10631072
}
10641073

1074+
egli_glvnd_icd_from_json() {
1075+
# Extract ICD library_path from a GLVND EGL vendor JSON (no jq).
1076+
# Prints the value (e.g., libEGL_adreno.so.1) or empty on failure.
1077+
f="$1"
1078+
[ -r "$f" ] || { printf '%s\n' ""; return 0; }
1079+
1080+
# Match a line containing "library_path" : "...."
1081+
# Keep it resilient to whitespace.
1082+
sed -n 's/.*"library_path"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$f" | head -n 1
1083+
}
1084+
1085+
egli_glvnd_icd_from_json() {
1086+
# Extract ICD library_path from a GLVND EGL vendor JSON (no jq).
1087+
# Prints the value (e.g., libEGL_adreno.so.1) or empty on failure.
1088+
f="$1"
1089+
[ -r "$f" ] || { printf '%s\n' ""; return 0; }
1090+
1091+
# Match a line containing "library_path" : "...."
1092+
# Keep it resilient to whitespace.
1093+
sed -n 's/.*"library_path"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$f" | head -n 1
1094+
}
1095+
1096+
egli_derive_driver_name() {
1097+
# Best-effort for log readability only.
1098+
# Inputs: gl_vendor gl_renderer
1099+
v="$1"
1100+
r="$2"
1101+
1102+
# Qualcomm/Adreno path
1103+
if printf '%s %s\n' "$v" "$r" | grep -Eqi '(qualcomm|adreno)'; then
1104+
icd=""
1105+
if [ -f /usr/share/glvnd/egl_vendor.d/10_EGL_adreno.json ]; then
1106+
icd="$(egli_glvnd_icd_from_json /usr/share/glvnd/egl_vendor.d/10_EGL_adreno.json)"
1107+
fi
1108+
if [ -n "$icd" ]; then
1109+
printf '%s\n' "adreno ($icd)"
1110+
return 0
1111+
fi
1112+
printf '%s\n' "adreno"
1113+
return 0
1114+
fi
1115+
1116+
# Mesa path
1117+
if printf '%s %s\n' "$v" "$r" | grep -Eqi '(mesa|llvmpipe|softpipe|swrast|lavapipe)'; then
1118+
icd=""
1119+
if [ -f /usr/share/glvnd/egl_vendor.d/50_mesa.json ]; then
1120+
icd="$(egli_glvnd_icd_from_json /usr/share/glvnd/egl_vendor.d/50_mesa.json)"
1121+
fi
1122+
if [ -n "$icd" ]; then
1123+
printf '%s\n' "mesa ($icd)"
1124+
return 0
1125+
fi
1126+
printf '%s\n' "mesa"
1127+
return 0
1128+
fi
1129+
1130+
printf '%s\n' "unknown"
1131+
return 0
1132+
}
1133+
10651134
egli_get_field() {
10661135
key="$1"
10671136
awk -v k="$key" '
@@ -1142,6 +1211,32 @@ egli_classify_pipeline() {
11421211
return 0
11431212
}
11441213

1214+
egli_wayland_socket_ok() {
1215+
wd="${WAYLAND_DISPLAY:-}"
1216+
[ -n "$wd" ] || return 1
1217+
1218+
case "$wd" in
1219+
/*)
1220+
[ -S "$wd" ] && return 0
1221+
return 1
1222+
;;
1223+
*)
1224+
xrd="${XDG_RUNTIME_DIR:-}"
1225+
if [ -n "$xrd" ]; then
1226+
[ -S "$xrd/$wd" ] && return 0
1227+
return 1
1228+
fi
1229+
1230+
# Fallbacks when XDG_RUNTIME_DIR is unset (common in minimal shells)
1231+
[ -S "/run/user/0/$wd" ] && return 0
1232+
[ -S "/run/user/1000/$wd" ] && return 0
1233+
[ -S "/run/$wd" ] && return 0
1234+
1235+
return 1
1236+
;;
1237+
esac
1238+
}
1239+
11451240
egli_print_legacy() {
11461241
plat="$1"
11471242
driver="$2"
@@ -1182,9 +1277,9 @@ egli_try_one_platform() {
11821277
egl_api_ver="$(printf '%s\n' "$out" | egli_get_field "EGL API version")"
11831278

11841279
ok=0
1185-
if [ -n "$egl_vendor" ]; then ok=1; fi
1186-
if [ -n "$egl_version" ]; then ok=1; fi
1187-
if [ -n "$egl_api_ver" ]; then ok=1; fi
1280+
[ -n "$egl_vendor" ] && ok=1
1281+
[ -n "$egl_version" ] && ok=1
1282+
[ -n "$egl_api_ver" ] && ok=1
11881283

11891284
if [ "$rc" -ne 0 ] || [ "$ok" -eq 0 ]; then
11901285
log_warn "eglinfo platform '$plat' did not initialize cleanly (rc=$rc)."
@@ -1203,35 +1298,47 @@ egli_try_one_platform() {
12031298
"Driver name" \
12041299
"Driver")"
12051300

1206-
# GL vendor (prefer explicit GL_VENDOR if present)
1301+
# GL vendor
12071302
gl_vendor="$(egli_get_first "$out" \
12081303
"GL_VENDOR" \
12091304
"OpenGL ES profile vendor string" \
12101305
"OpenGL vendor string" \
12111306
"OpenGL ES vendor string")"
12121307

1213-
# GL renderer (prefer explicit GL_RENDERER if present)
1308+
# GL renderer
12141309
gl_renderer="$(egli_get_first "$out" \
12151310
"GL_RENDERER" \
12161311
"OpenGL ES profile renderer string" \
12171312
"OpenGL renderer string" \
12181313
"OpenGL ES renderer string")"
12191314

1220-
# NEW: avoid classification on empty strings
1315+
# Avoid classification on empty strings
12211316
[ -n "$driver" ] || driver="unknown"
12221317
[ -n "$gl_vendor" ] || gl_vendor="unknown"
12231318
[ -n "$gl_renderer" ] || gl_renderer="unknown"
12241319

1225-
# If we got nothing useful, treat as failure (prevents misleading GPU/CPU label)
1226-
if [ "$driver" = "unknown" ] && [ "$gl_vendor" = "unknown" ] && [ "$gl_renderer" = "unknown" ]; then
1227-
log_warn "eglinfo platform '$plat' returned no driver/vendor/renderer strings; skipping classification."
1228-
return 1
1320+
# If eglinfo didn't expose a driver name, derive one from GLVND JSON + strings
1321+
if [ "$driver" = "unknown" ]; then
1322+
driver="$(egli_derive_driver_name "$gl_vendor" "$gl_renderer")"
12291323
fi
12301324

1231-
# Print GPU/CPU pipeline type (align to your sample: no extra indentation)
1325+
# Print GPU/CPU pipeline type
12321326
pipe_kind="$(egli_classify_pipeline "$driver" "$gl_vendor" "$gl_renderer")"
12331327
log_info "EGLINFO: Pipeline type: $pipe_kind"
12341328

1329+
# ---- Cache what we used, so decision uses the same data ----
1330+
EGLI_LAST_PLATFORM="$plat"
1331+
EGLI_LAST_DRIVER="$driver"
1332+
EGLI_LAST_GL_VENDOR="$gl_vendor"
1333+
EGLI_LAST_GL_RENDERER="$gl_renderer"
1334+
EGLI_LAST_PIPE_KIND="$pipe_kind"
1335+
if [ "${EGLINFO_CACHE_OUTPUT:-0}" = "1" ]; then
1336+
EGLI_LAST_OUT="$out"
1337+
else
1338+
EGLI_LAST_OUT=""
1339+
fi
1340+
# -----------------------------------------------------------
1341+
12351342
egli_print_legacy "$plat" "$driver" "$gl_vendor" "$gl_renderer"
12361343
return 0
12371344
}
@@ -1240,20 +1347,28 @@ display_print_eglinfo_pipeline() {
12401347
# Usage: display_print_eglinfo_pipeline auto|wayland|gbm|device|surfaceless
12411348
mode="${1:-auto}"
12421349

1350+
# Clear cached result on every call (prevents stale decisions)
1351+
EGLI_LAST_PLATFORM=""
1352+
EGLI_LAST_DRIVER=""
1353+
EGLI_LAST_GL_VENDOR=""
1354+
EGLI_LAST_GL_RENDERER=""
1355+
EGLI_LAST_PIPE_KIND=""
1356+
EGLI_LAST_OUT=""
1357+
12431358
EGLINFO="${EGLINFO:-eglinfo}"
12441359
if ! command -v "$EGLINFO" >/dev/null 2>&1; then
12451360
log_error "eglinfo not found (EGLINFO='$EGLINFO')"
12461361
return 1
12471362
fi
12481363

1249-
# NOTE: unchanged usage; now egli_pick_platform_flag can return 1
1250-
# but when it does, plat_flag will be empty and caller already checked eglinfo.
1364+
# egli_pick_platform_flag may return non-zero; treat empty as "use EGL_PLATFORM="
12511365
plat_flag="$(egli_pick_platform_flag 2>/dev/null)" || plat_flag=""
12521366

12531367
log_info "---------------- EGLINFO pipeline detection (select one) ----------------"
12541368

12551369
if [ "$mode" = "auto" ]; then
1256-
if [ -n "${WAYLAND_DISPLAY:-}" ]; then
1370+
# Prefer wayland only if the socket really exists (base/prop handled)
1371+
if egli_wayland_socket_ok; then
12571372
if egli_try_one_platform "wayland" "$plat_flag"; then
12581373
log_info "---------------- End EGLINFO pipeline detection --------------------------"
12591374
return 0
@@ -1282,18 +1397,24 @@ display_print_eglinfo_pipeline() {
12821397

12831398
case "$mode" in
12841399
wayland|gbm|device|surfaceless)
1285-
if ! egli_try_one_platform "$mode" "$plat_flag"; then
1400+
# If user explicitly requested wayland but socket is not present, warn and fallback
1401+
if [ "$mode" = "wayland" ] && ! egli_wayland_socket_ok; then
1402+
log_warn "Requested 'wayland' but WAYLAND_DISPLAY socket is not present; trying fallbacks..."
1403+
else
1404+
if egli_try_one_platform "$mode" "$plat_flag"; then
1405+
log_info "---------------- End EGLINFO pipeline detection --------------------------"
1406+
return 0
1407+
fi
12861408
log_warn "Requested '$mode' did not work. Trying fallbacks..."
1409+
fi
12871410

1288-
if ! egli_try_one_platform "gbm" "$plat_flag"; then
1289-
if ! egli_try_one_platform "device" "$plat_flag"; then
1290-
if ! egli_try_one_platform "surfaceless" "$plat_flag"; then
1291-
if ! egli_try_one_platform "wayland" "$plat_flag"; then
1292-
log_warn "No fallback platforms worked either."
1293-
fi
1294-
fi
1295-
fi
1296-
fi
1411+
# Fallback order: gbm -> device -> surfaceless -> wayland (last)
1412+
if egli_try_one_platform "gbm" "$plat_flag"; then :;
1413+
elif egli_try_one_platform "device" "$plat_flag"; then :;
1414+
elif egli_try_one_platform "surfaceless" "$plat_flag"; then :;
1415+
elif egli_wayland_socket_ok && egli_try_one_platform "wayland" "$plat_flag"; then :;
1416+
else
1417+
log_warn "No fallback platforms worked either."
12971418
fi
12981419

12991420
log_info "---------------- End EGLINFO pipeline detection --------------------------"
@@ -1312,102 +1433,21 @@ display_print_eglinfo_pipeline() {
13121433
###############################################################################
13131434
display_is_cpu_renderer() {
13141435
# Usage: display_is_cpu_renderer <mode>
1315-
# Prints EGLINFO block when called (your requirement).
1436+
# Prints EGLINFO block via display_print_eglinfo_pipeline().
13161437
# Returns: 0 if CPU/software renderer detected, 1 otherwise (GPU or unknown)
13171438
mode="${1:-auto}"
13181439

1319-
# Always print EGLINFO pipeline detection (do NOT redirect)
1440+
# Print + cache a single selected platform (no re-run of eglinfo for decision)
13201441
display_print_eglinfo_pipeline "$mode" || true
13211442

1322-
EGLINFO="${EGLINFO:-eglinfo}"
1323-
if ! command -v "$EGLINFO" >/dev/null 2>&1; then
1443+
# If we couldn't cache anything usable, do NOT claim CPU.
1444+
if [ -z "${EGLI_LAST_PIPE_KIND:-}" ]; then
13241445
return 1
13251446
fi
13261447

1327-
# NOTE: unchanged usage; now egli_pick_platform_flag can return 1
1328-
plat_flag="$(egli_pick_platform_flag 2>/dev/null)" || plat_flag=""
1329-
1330-
# Run eglinfo and decide CPU/software for one platform.
1331-
# Return 0 if CPU/software, 1 otherwise.
1332-
egli_is_cpu_for_platform() {
1333-
p="$1"
1334-
1335-
if [ -n "$plat_flag" ]; then
1336-
out="$("$EGLINFO" "$plat_flag" "$p" 2>&1)"
1337-
rc=$?
1338-
else
1339-
out="$(EGL_PLATFORM="$p" "$EGLINFO" 2>&1)"
1340-
rc=$?
1341-
fi
1342-
1343-
# Must initialize
1344-
egl_vendor="$(printf '%s\n' "$out" | egli_get_field "EGL vendor string")"
1345-
egl_version="$(printf '%s\n' "$out" | egli_get_field "EGL version string")"
1346-
egl_api_ver="$(printf '%s\n' "$out" | egli_get_field "EGL API version")"
1347-
1348-
ok=0
1349-
if [ -n "$egl_vendor" ]; then ok=1; fi
1350-
if [ -n "$egl_version" ]; then ok=1; fi
1351-
if [ -n "$egl_api_ver" ]; then ok=1; fi
1352-
if [ "$rc" -ne 0 ] || [ "$ok" -eq 0 ]; then
1353-
return 1
1354-
fi
1355-
1356-
driver="$(egli_get_first "$out" \
1357-
"EGL driver name" \
1358-
"EGL driver" \
1359-
"Driver name" \
1360-
"Driver")"
1361-
1362-
gl_vendor="$(egli_get_first "$out" \
1363-
"GL_VENDOR" \
1364-
"OpenGL ES profile vendor string" \
1365-
"OpenGL vendor string" \
1366-
"OpenGL ES vendor string")"
1367-
1368-
gl_renderer="$(egli_get_first "$out" \
1369-
"GL_RENDERER" \
1370-
"OpenGL ES profile renderer string" \
1371-
"OpenGL renderer string" \
1372-
"OpenGL ES renderer string")"
1373-
1374-
# NEW: avoid classification on empty strings
1375-
[ -n "$driver" ] || driver="unknown"
1376-
[ -n "$gl_vendor" ] || gl_vendor="unknown"
1377-
[ -n "$gl_renderer" ] || gl_renderer="unknown"
1378-
1379-
# If we got nothing useful, treat as not-CPU (unknown) rather than mislabel
1380-
if [ "$driver" = "unknown" ] && [ "$gl_vendor" = "unknown" ] && [ "$gl_renderer" = "unknown" ]; then
1381-
return 1
1382-
fi
1383-
1384-
pipe_kind="$(egli_classify_pipeline "$driver" "$gl_vendor" "$gl_renderer")"
1385-
if printf '%s\n' "$pipe_kind" | grep -qi '^CPU'; then
1386-
return 0
1387-
fi
1388-
return 1
1389-
}
1390-
1391-
if [ "$mode" = "auto" ]; then
1392-
# Match display_print_eglinfo_pipeline(auto) preference order.
1393-
if [ -n "${WAYLAND_DISPLAY:-}" ]; then
1394-
if egli_is_cpu_for_platform "wayland"; then return 0; fi
1395-
fi
1396-
if egli_is_cpu_for_platform "gbm"; then return 0; fi
1397-
if egli_is_cpu_for_platform "device"; then return 0; fi
1398-
if egli_is_cpu_for_platform "surfaceless"; then return 0; fi
1399-
return 1
1448+
if printf '%s\n' "$EGLI_LAST_PIPE_KIND" | grep -qi '^CPU'; then
1449+
return 0
14001450
fi
14011451

1402-
case "$mode" in
1403-
wayland|gbm|device|surfaceless)
1404-
if egli_is_cpu_for_platform "$mode"; then
1405-
return 0
1406-
fi
1407-
return 1
1408-
;;
1409-
*)
1410-
return 1
1411-
;;
1412-
esac
1452+
return 1
14131453
}

0 commit comments

Comments
 (0)