@@ -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