Skip to content

Commit 558a937

Browse files
committed
display: add shared FPS parsing and policy helpers
Update Runner/utils/lib_display.sh to add reusable helpers for display FPS validation: - display_parse_fps_log() - display_resolve_fps_policy() - display_apply_fps_refresh_policy() - display_fps_gate_avg() These helpers centralize FPS parsing, expectation mode resolution, refresh-policy application, and FPS gating so display test run.sh scripts can stay thin and reuse the same logic across platforms with different refresh rates. Signed-off-by: Srikanth Muppandam <smuppand@qti.qualcomm.com>
1 parent 5036042 commit 558a937

1 file changed

Lines changed: 222 additions & 0 deletions

File tree

Runner/utils/lib_display.sh

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1617,3 +1617,225 @@ display_screenshot_delta_end() {
16171617
log_info "Screenshot delta check changed visual validation OK"
16181618
return 0
16191619
}
1620+
1621+
# Resolve FPS expectation policy for display tests.
1622+
# Sets DISPLAY_FPS_* globals from FPS_EXPECT_MODE / EXPECT_FPS / detected refresh.
1623+
display_resolve_fps_policy() {
1624+
DISPLAY_FPS_MODE=""
1625+
DISPLAY_FPS_EXPECTED=""
1626+
DISPLAY_FPS_DETECTED_HZ=""
1627+
DISPLAY_FPS_MIN_OK=""
1628+
DISPLAY_FPS_MAX_OK=""
1629+
1630+
fps_mode="${FPS_EXPECT_MODE:-auto}"
1631+
fps_expect="${EXPECT_FPS:-}"
1632+
fps_default="${EXPECT_FPS_DEFAULT:-60}"
1633+
fps_tol="${FPS_TOL_PCT:-10}"
1634+
fps_min_pct="${MIN_FPS_PCT:-85}"
1635+
1636+
case "$fps_mode" in
1637+
auto)
1638+
if [ -n "$fps_expect" ]; then
1639+
DISPLAY_FPS_MODE="fixed"
1640+
else
1641+
DISPLAY_FPS_MODE="detected"
1642+
fi
1643+
;;
1644+
fixed|detected)
1645+
DISPLAY_FPS_MODE="$fps_mode"
1646+
;;
1647+
*)
1648+
log_warn "display_resolve_fps_policy: unknown FPS_EXPECT_MODE='$fps_mode', defaulting to auto"
1649+
if [ -n "$fps_expect" ]; then
1650+
DISPLAY_FPS_MODE="fixed"
1651+
else
1652+
DISPLAY_FPS_MODE="detected"
1653+
fi
1654+
;;
1655+
esac
1656+
1657+
if [ "$DISPLAY_FPS_MODE" = "detected" ]; then
1658+
if command -v weston_get_primary_refresh_hz >/dev/null 2>&1; then
1659+
DISPLAY_FPS_DETECTED_HZ="$(weston_get_primary_refresh_hz 2>/dev/null || true)"
1660+
fi
1661+
1662+
case "$DISPLAY_FPS_DETECTED_HZ" in
1663+
''|*[!0-9.]*)
1664+
DISPLAY_FPS_MODE="fixed"
1665+
if [ -n "$fps_expect" ]; then
1666+
DISPLAY_FPS_EXPECTED="$fps_expect"
1667+
log_warn "display_resolve_fps_policy: refresh detect failed, falling back to fixed EXPECT_FPS=$DISPLAY_FPS_EXPECTED"
1668+
else
1669+
DISPLAY_FPS_EXPECTED="$fps_default"
1670+
log_warn "display_resolve_fps_policy: refresh detect failed, falling back to fixed EXPECT_FPS_DEFAULT=$DISPLAY_FPS_EXPECTED"
1671+
fi
1672+
;;
1673+
*)
1674+
DISPLAY_FPS_EXPECTED="$(printf '%s\n' "$DISPLAY_FPS_DETECTED_HZ" | awk '{printf "%.0f\n", $1 + 0.0}')"
1675+
DISPLAY_FPS_MIN_OK="$(awk -v f="$DISPLAY_FPS_EXPECTED" -v p="$fps_min_pct" 'BEGIN { printf "%.0f\n", f * p / 100.0 }')"
1676+
log_info "FPS policy: mode=detected refresh=${DISPLAY_FPS_DETECTED_HZ}Hz expected=${DISPLAY_FPS_EXPECTED} min_ok=${DISPLAY_FPS_MIN_OK}"
1677+
return 0
1678+
;;
1679+
esac
1680+
fi
1681+
1682+
if [ -z "$DISPLAY_FPS_EXPECTED" ]; then
1683+
if [ -n "$fps_expect" ]; then
1684+
DISPLAY_FPS_EXPECTED="$fps_expect"
1685+
else
1686+
DISPLAY_FPS_EXPECTED="$fps_default"
1687+
fi
1688+
fi
1689+
1690+
DISPLAY_FPS_MIN_OK="$(awk -v f="$DISPLAY_FPS_EXPECTED" -v t="$fps_tol" 'BEGIN { printf "%.0f\n", f * (100.0 - t) / 100.0 }')"
1691+
DISPLAY_FPS_MAX_OK="$(awk -v f="$DISPLAY_FPS_EXPECTED" -v t="$fps_tol" 'BEGIN { printf "%.0f\n", f * (100.0 + t) / 100.0 }')"
1692+
1693+
log_info "FPS policy: mode=fixed expected=${DISPLAY_FPS_EXPECTED} range=[${DISPLAY_FPS_MIN_OK}, ${DISPLAY_FPS_MAX_OK}]"
1694+
return 0
1695+
}
1696+
1697+
# Apply refresh policy for display tests.
1698+
# Fixed ~60 FPS target gets best-effort 60Hz normalization; detected mode keeps native refresh.
1699+
display_apply_fps_refresh_policy() {
1700+
if [ -z "${DISPLAY_FPS_MODE:-}" ] || [ -z "${DISPLAY_FPS_EXPECTED:-}" ]; then
1701+
log_warn "display_apply_fps_refresh_policy: FPS policy not resolved"
1702+
return 1
1703+
fi
1704+
1705+
if [ "$DISPLAY_FPS_MODE" = "detected" ]; then
1706+
log_info "Detected FPS mode selected; keeping native refresh"
1707+
return 0
1708+
fi
1709+
1710+
if hz_is_about_60 "${DISPLAY_FPS_EXPECTED}"; then
1711+
if command -v weston_force_primary_1080p60_if_not_60 >/dev/null 2>&1; then
1712+
log_info "Fixed ~60 FPS policy selected; ensuring primary output is ~60Hz (best-effort)"
1713+
if weston_force_primary_1080p60_if_not_60; then
1714+
log_info "Primary output is ~60Hz (or was already ~60Hz)"
1715+
else
1716+
log_warn "Unable to force ~60Hz (continuing; not a hard failure)"
1717+
fi
1718+
else
1719+
log_warn "weston_force_primary_1080p60_if_not_60 helper not found; skipping ~60Hz enforcement"
1720+
fi
1721+
else
1722+
log_info "Fixed FPS policy selected with expected=${DISPLAY_FPS_EXPECTED}; no refresh normalization applied"
1723+
fi
1724+
1725+
return 0
1726+
}
1727+
1728+
# Gate measured FPS against the resolved display FPS policy.
1729+
# Returns 0 for pass, 1 for fail. Logs the reason internally.
1730+
display_fps_gate_avg() {
1731+
fps_avg="$1"
1732+
fps_count="$2"
1733+
require_fps="${REQUIRE_FPS:-1}"
1734+
1735+
if [ "$require_fps" -eq 0 ]; then
1736+
if [ "$fps_count" -eq 0 ]; then
1737+
log_warn "REQUIRE_FPS=0 and no FPS samples found; skipping FPS gating"
1738+
else
1739+
log_info "REQUIRE_FPS=0; FPS stats recorded but not used for gating"
1740+
fi
1741+
return 0
1742+
fi
1743+
1744+
if [ "$fps_count" -eq 0 ]; then
1745+
log_fail "FPS gating enabled but no FPS samples were found"
1746+
return 1
1747+
fi
1748+
1749+
fps_int="$(printf '%s\n' "$fps_avg" | awk 'BEGIN {v=0} {v=$1+0.0} END {printf "%.0f\n", v}')"
1750+
1751+
if [ "${DISPLAY_FPS_MODE:-}" = "detected" ]; then
1752+
if [ -z "${DISPLAY_FPS_MIN_OK:-}" ]; then
1753+
log_fail "Detected FPS policy missing minimum threshold"
1754+
return 1
1755+
fi
1756+
1757+
if [ "$fps_int" -lt "$DISPLAY_FPS_MIN_OK" ]; then
1758+
log_fail "Average FPS below detected-refresh threshold: avg=${fps_avg} (~${fps_int}) < ${DISPLAY_FPS_MIN_OK} (refresh=${DISPLAY_FPS_DETECTED_HZ}Hz)"
1759+
return 1
1760+
fi
1761+
1762+
log_info "Detected-refresh FPS gate passed: avg=${fps_avg} (~${fps_int}) >= ${DISPLAY_FPS_MIN_OK} (refresh=${DISPLAY_FPS_DETECTED_HZ}Hz)"
1763+
return 0
1764+
fi
1765+
1766+
if [ -z "${DISPLAY_FPS_MIN_OK:-}" ] || [ -z "${DISPLAY_FPS_MAX_OK:-}" ]; then
1767+
log_fail "Fixed FPS policy missing valid range"
1768+
return 1
1769+
fi
1770+
1771+
if [ "$fps_int" -lt "$DISPLAY_FPS_MIN_OK" ] || [ "$fps_int" -gt "$DISPLAY_FPS_MAX_OK" ]; then
1772+
log_fail "Average FPS out of range: avg=${fps_avg} (~${fps_int}) not in [${DISPLAY_FPS_MIN_OK}, ${DISPLAY_FPS_MAX_OK}] (expected=${DISPLAY_FPS_EXPECTED})"
1773+
return 1
1774+
fi
1775+
1776+
log_info "Fixed FPS gate passed: avg=${fps_avg} (~${fps_int}) in [${DISPLAY_FPS_MIN_OK}, ${DISPLAY_FPS_MAX_OK}]"
1777+
return 0
1778+
}
1779+
1780+
# Parse FPS samples from a weston-simple-egl style log.
1781+
# Sets DISPLAY_FPS_COUNT / DISPLAY_FPS_AVG / DISPLAY_FPS_MIN / DISPLAY_FPS_MAX.
1782+
display_parse_fps_log() {
1783+
logf="$1"
1784+
1785+
DISPLAY_FPS_COUNT=0
1786+
DISPLAY_FPS_AVG="-"
1787+
DISPLAY_FPS_MIN="-"
1788+
DISPLAY_FPS_MAX="-"
1789+
1790+
[ -n "$logf" ] || return 1
1791+
[ -r "$logf" ] || return 1
1792+
1793+
fps_stats=$(
1794+
awk '
1795+
/[0-9]+[[:space:]]+frames in[[:space:]]+[0-9]+[[:space:]]+seconds/ {
1796+
val = $(NF-1) + 0.0
1797+
all_n++
1798+
all_vals[all_n] = val
1799+
}
1800+
END {
1801+
if (all_n == 0) exit
1802+
1803+
if (all_n == 1) {
1804+
n = 1
1805+
sum = all_vals[1]
1806+
min = all_vals[1]
1807+
max = all_vals[1]
1808+
} else {
1809+
n = 0
1810+
sum = 0.0
1811+
for (i = 2; i <= all_n; i++) {
1812+
v = all_vals[i]
1813+
n++
1814+
sum += v
1815+
if (n == 1 || v < min) min = v
1816+
if (n == 1 || v > max) max = v
1817+
}
1818+
}
1819+
1820+
if (n > 0) {
1821+
avg = sum / n
1822+
printf "n=%d avg=%f min=%f max=%f\n", n, avg, min, max
1823+
}
1824+
}
1825+
' "$logf" 2>/dev/null || true
1826+
)
1827+
1828+
[ -n "$fps_stats" ] || return 1
1829+
1830+
DISPLAY_FPS_COUNT=$(printf '%s\n' "$fps_stats" | awk '{print $1}' | sed 's/^n=//')
1831+
DISPLAY_FPS_AVG=$(printf '%s\n' "$fps_stats" | awk '{print $2}' | sed 's/^avg=//')
1832+
DISPLAY_FPS_MIN=$(printf '%s\n' "$fps_stats" | awk '{print $3}' | sed 's/^min=//')
1833+
DISPLAY_FPS_MAX=$(printf '%s\n' "$fps_stats" | awk '{print $4}' | sed 's/^max=//')
1834+
1835+
case "$DISPLAY_FPS_COUNT" in ''|*[!0-9]*) DISPLAY_FPS_COUNT=0 ;; esac
1836+
[ -n "$DISPLAY_FPS_AVG" ] || DISPLAY_FPS_AVG="-"
1837+
[ -n "$DISPLAY_FPS_MIN" ] || DISPLAY_FPS_MIN="-"
1838+
[ -n "$DISPLAY_FPS_MAX" ] || DISPLAY_FPS_MAX="-"
1839+
1840+
return 0
1841+
}

0 commit comments

Comments
 (0)