diff --git a/Runner/suites/Multimedia/Graphics/weston-simple-egl/run.sh b/Runner/suites/Multimedia/Graphics/weston-simple-egl/run.sh index 6a7470c1..04442078 100755 --- a/Runner/suites/Multimedia/Graphics/weston-simple-egl/run.sh +++ b/Runner/suites/Multimedia/Graphics/weston-simple-egl/run.sh @@ -52,18 +52,21 @@ RUN_LOG="./${TESTNAME}_run.log" # --------------------------------------------------------------------------- DURATION="${DURATION:-30s}" STOP_GRACE="${STOP_GRACE:-3s}" -EXPECT_FPS="${EXPECT_FPS:-60}" +FPS_EXPECT_MODE="${FPS_EXPECT_MODE:-auto}" +EXPECT_FPS="${EXPECT_FPS:-}" +EXPECT_FPS_DEFAULT="${EXPECT_FPS_DEFAULT:-60}" FPS_TOL_PCT="${FPS_TOL_PCT:-10}" +MIN_FPS_PCT="${MIN_FPS_PCT:-85}" REQUIRE_FPS="${REQUIRE_FPS:-1}" # Detect overlay by presence of Adreno GLVND vendor JSON BUILD_FLAVOUR="base" EGL_VENDOR_JSON="" - + # Check common vendor JSON locations and filename patterns for d in /usr/share/glvnd/egl_vendor.d /etc/glvnd/egl_vendor.d; do [ -d "$d" ] || continue - + # Try both naming styles: 10_adreno.json and 10_EGL_adreno.json for f in "$d"/*adreno*.json "$d"/*EGL_adreno*.json; do [ -e "$f" ] || continue @@ -74,24 +77,23 @@ for d in /usr/share/glvnd/egl_vendor.d /etc/glvnd/egl_vendor.d; do fi done done - + log_info "Weston log directory: $SCRIPT_DIR" log_info "--------------------------------------------------------------------------" log_info "------------------- Starting ${TESTNAME} Testcase --------------------------" - + # Optional platform details (helper from functestlib) if command -v detect_platform >/dev/null 2>&1; then detect_platform fi - + if [ "$BUILD_FLAVOUR" = "overlay" ]; then log_info "Build flavor: overlay (EGL vendor JSON present: ${EGL_VENDOR_JSON})" else log_info "Build flavor: base (no Adreno EGL vendor JSON found)" fi -log_info "Config: DURATION=${DURATION} STOP_GRACE=${STOP_GRACE} EXPECT_FPS=${EXPECT_FPS}+/-${FPS_TOL_PCT}% REQUIRE_FPS=${REQUIRE_FPS} BUILD_FLAVOUR=${BUILD_FLAVOUR}" - +log_info "Input config: DURATION=${DURATION} STOP_GRACE=${STOP_GRACE} FPS_EXPECT_MODE=${FPS_EXPECT_MODE} EXPECT_FPS=${EXPECT_FPS:-} EXPECT_FPS_DEFAULT=${EXPECT_FPS_DEFAULT} (fallback) FPS_TOL_PCT=${FPS_TOL_PCT}% MIN_FPS_PCT=${MIN_FPS_PCT}% REQUIRE_FPS=${REQUIRE_FPS} BUILD_FLAVOUR=${BUILD_FLAVOUR}" # --------------------------------------------------------------------------- # Display snapshot # --------------------------------------------------------------------------- @@ -224,29 +226,31 @@ else log_warn "wayland_connection_ok helper not found continuing without explicit Wayland probe." fi +if ! display_resolve_fps_policy; then + log_fail "Failed to resolve FPS policy" + echo "${TESTNAME} FAIL" >"$RES_FILE" + exit 0 +fi + +if [ "${DISPLAY_FPS_MODE:-}" = "detected" ]; then + log_info "Resolved FPS policy: mode=${DISPLAY_FPS_MODE} refresh=${DISPLAY_FPS_DETECTED_HZ}Hz expected=${DISPLAY_FPS_EXPECTED} min_ok=${DISPLAY_FPS_MIN_OK}" +else + log_info "Resolved FPS policy: mode=${DISPLAY_FPS_MODE} expected=${DISPLAY_FPS_EXPECTED} range=[${DISPLAY_FPS_MIN_OK}, ${DISPLAY_FPS_MAX_OK}]" +fi # --------------------------------------------------------------------------- -# Ensure primary output is ~60Hz (best-effort, no churn if already ~60Hz) +# Apply refresh policy resolved in lib_display.sh # --------------------------------------------------------------------------- if command -v display_debug_snapshot >/dev/null 2>&1; then - display_debug_snapshot "${TESTNAME}: before-ensure-60hz" + display_debug_snapshot "${TESTNAME}: before-refresh-policy" fi if command -v wayland_debug_snapshot >/dev/null 2>&1; then - wayland_debug_snapshot "${TESTNAME}: before-ensure-60hz" + wayland_debug_snapshot "${TESTNAME}: before-refresh-policy" fi -if command -v weston_force_primary_1080p60_if_not_60 >/dev/null 2>&1; then - log_info "Ensuring primary output is ~60Hz (best-effort) ..." - if weston_force_primary_1080p60_if_not_60; then - log_info "Primary output is ~60Hz (or was already ~60Hz)." - else - log_warn "Unable to force ~60Hz (continuing; not a hard failure)." - fi -else - log_warn "weston_force_primary_1080p60_if_not_60 helper not found; skipping ~60Hz enforcement." -fi +display_apply_fps_refresh_policy || true if command -v display_debug_snapshot >/dev/null 2>&1; then - display_debug_snapshot "${TESTNAME}: after-ensure-60hz" + display_debug_snapshot "${TESTNAME}: after-refresh-policy" fi # --- Skip if only CPU/software renderer is active (GPU HW accel not enabled) --- @@ -328,51 +332,19 @@ log_info "Client finished: rc=${rc} elapsed=${elapsed}s" # FPS parsing: average / min / max from all intervals # - Discard FIRST sample as warm-up if we have 2+ samples. # --------------------------------------------------------------------------- +# --------------------------------------------------------------------------- +# FPS parsing +# --------------------------------------------------------------------------- fps_count=0 fps_avg="-" fps_min="-" fps_max="-" -fps_stats=$( - awk ' - /[0-9]+[[:space:]]+frames in[[:space:]]+[0-9]+[[:space:]]+seconds/ { - val = $(NF-1) + 0.0 - all_n++ - all_vals[all_n] = val - } - END { - if (all_n == 0) exit - - if (all_n == 1) { - n = 1 - sum = all_vals[1] - min = all_vals[1] - max = all_vals[1] - } else { - n = 0 - sum = 0.0 - for (i = 2; i <= all_n; i++) { - v = all_vals[i] - n++ - sum += v - if (n == 1 || v < min) min = v - if (n == 1 || v > max) max = v - } - } - - if (n > 0) { - avg = sum / n - printf "n=%d avg=%f min=%f max=%f\n", n, avg, min, max - } - }' "$RUN_LOG" 2>/dev/null || true -) - -if [ -n "$fps_stats" ]; then - fps_count=$(printf '%s\n' "$fps_stats" | awk '{print $1}' | sed 's/^n=//') - fps_avg=$(printf '%s\n' "$fps_stats" | awk '{print $2}' | sed 's/^avg=//') - fps_min=$(printf '%s\n' "$fps_stats" | awk '{print $3}' | sed 's/^min=//') - fps_max=$(printf '%s\n' "$fps_stats" | awk '{print $4}' | sed 's/^max=//') - +if display_parse_fps_log "$RUN_LOG"; then + fps_count="$DISPLAY_FPS_COUNT" + fps_avg="$DISPLAY_FPS_AVG" + fps_min="$DISPLAY_FPS_MIN" + fps_max="$DISPLAY_FPS_MAX" log_info "FPS stats from ${RUN_LOG}: samples=${fps_count} avg=${fps_avg} min=${fps_min} max=${fps_max}" else log_warn "No FPS lines detected in ${RUN_LOG} weston-simple-egl may not have emitted FPS stats (or output was truncated)." @@ -383,7 +355,11 @@ if [ "$fps_count" -eq 0 ]; then fps_for_summary="-" fi -log_info "Result summary: rc=${rc} elapsed=${elapsed}s fps=${fps_for_summary} (expected ~${EXPECT_FPS}+/-${FPS_TOL_PCT}%)" +if [ "${DISPLAY_FPS_MODE:-}" = "detected" ]; then + log_info "Result summary: rc=${rc} elapsed=${elapsed}s fps=${fps_for_summary} mode=${DISPLAY_FPS_MODE} refresh=${DISPLAY_FPS_DETECTED_HZ}Hz expected=${DISPLAY_FPS_EXPECTED} min_ok=${DISPLAY_FPS_MIN_OK}" +else + log_info "Result summary: rc=${rc} elapsed=${elapsed}s fps=${fps_for_summary} mode=${DISPLAY_FPS_MODE} expected=${DISPLAY_FPS_EXPECTED} range=[${DISPLAY_FPS_MIN_OK}, ${DISPLAY_FPS_MAX_OK}]" +fi # --------------------------------------------------------------------------- # PASS / FAIL decision @@ -401,28 +377,8 @@ if [ "$elapsed" -le 1 ]; then final="FAIL" fi -# FPS gating if explicitly required -if [ "$REQUIRE_FPS" -ne 0 ]; then - if [ "$fps_count" -eq 0 ]; then - log_fail "FPS gating enabled (REQUIRE_FPS=${REQUIRE_FPS}) but no FPS samples were found treating as FAIL." - final="FAIL" - else - min_ok=$(awk -v f="$EXPECT_FPS" -v tol="$FPS_TOL_PCT" 'BEGIN { printf "%.0f\n", f * (100.0 - tol) / 100.0 }') - max_ok=$(awk -v f="$EXPECT_FPS" -v tol="$FPS_TOL_PCT" 'BEGIN { printf "%.0f\n", f * (100.0 + tol) / 100.0 }') - - fps_int=$(printf '%s\n' "$fps_avg" | awk 'BEGIN {v=0} {v=$1+0.0} END {printf "%.0f\n", v}') - - if [ "$fps_int" -lt "$min_ok" ] || [ "$fps_int" -gt "$max_ok" ]; then - log_fail "Average FPS out of range: avg=${fps_avg} (~${fps_int}) not in [${min_ok}, ${max_ok}] (EXPECT_FPS=${EXPECT_FPS}, tol=${FPS_TOL_PCT}%)." - final="FAIL" - fi - fi -else - if [ "$fps_count" -eq 0 ]; then - log_warn "REQUIRE_FPS=0 and no FPS samples found skipping FPS gating." - else - log_info "REQUIRE_FPS=0 FPS stats recorded but not used for gating." - fi +if ! display_fps_gate_avg "$fps_avg" "$fps_count"; then + final="FAIL" fi log_info "Final decision for ${TESTNAME}: ${final}" diff --git a/Runner/utils/lib_display.sh b/Runner/utils/lib_display.sh index af683375..0feaded2 100755 --- a/Runner/utils/lib_display.sh +++ b/Runner/utils/lib_display.sh @@ -1617,3 +1617,225 @@ display_screenshot_delta_end() { log_info "Screenshot delta check changed visual validation OK" return 0 } + +# Resolve FPS expectation policy for display tests. +# Sets DISPLAY_FPS_* globals from FPS_EXPECT_MODE / EXPECT_FPS / detected refresh. +display_resolve_fps_policy() { + DISPLAY_FPS_MODE="" + DISPLAY_FPS_EXPECTED="" + DISPLAY_FPS_DETECTED_HZ="" + DISPLAY_FPS_MIN_OK="" + DISPLAY_FPS_MAX_OK="" + + fps_mode="${FPS_EXPECT_MODE:-auto}" + fps_expect="${EXPECT_FPS:-}" + fps_default="${EXPECT_FPS_DEFAULT:-60}" + fps_tol="${FPS_TOL_PCT:-10}" + fps_min_pct="${MIN_FPS_PCT:-85}" + + case "$fps_mode" in + auto) + if [ -n "$fps_expect" ]; then + DISPLAY_FPS_MODE="fixed" + else + DISPLAY_FPS_MODE="detected" + fi + ;; + fixed|detected) + DISPLAY_FPS_MODE="$fps_mode" + ;; + *) + log_warn "display_resolve_fps_policy: unknown FPS_EXPECT_MODE='$fps_mode', defaulting to auto" + if [ -n "$fps_expect" ]; then + DISPLAY_FPS_MODE="fixed" + else + DISPLAY_FPS_MODE="detected" + fi + ;; + esac + + if [ "$DISPLAY_FPS_MODE" = "detected" ]; then + if command -v weston_get_primary_refresh_hz >/dev/null 2>&1; then + DISPLAY_FPS_DETECTED_HZ="$(weston_get_primary_refresh_hz 2>/dev/null || true)" + fi + + case "$DISPLAY_FPS_DETECTED_HZ" in + ''|*[!0-9.]*) + DISPLAY_FPS_MODE="fixed" + if [ -n "$fps_expect" ]; then + DISPLAY_FPS_EXPECTED="$fps_expect" + log_warn "display_resolve_fps_policy: refresh detect failed, falling back to fixed EXPECT_FPS=$DISPLAY_FPS_EXPECTED" + else + DISPLAY_FPS_EXPECTED="$fps_default" + log_warn "display_resolve_fps_policy: refresh detect failed, falling back to fixed EXPECT_FPS_DEFAULT=$DISPLAY_FPS_EXPECTED" + fi + ;; + *) + DISPLAY_FPS_EXPECTED="$(printf '%s\n' "$DISPLAY_FPS_DETECTED_HZ" | awk '{printf "%.0f\n", $1 + 0.0}')" + DISPLAY_FPS_MIN_OK="$(awk -v f="$DISPLAY_FPS_EXPECTED" -v p="$fps_min_pct" 'BEGIN { printf "%.0f\n", f * p / 100.0 }')" + log_info "FPS policy: mode=detected refresh=${DISPLAY_FPS_DETECTED_HZ}Hz expected=${DISPLAY_FPS_EXPECTED} min_ok=${DISPLAY_FPS_MIN_OK}" + return 0 + ;; + esac + fi + + if [ -z "$DISPLAY_FPS_EXPECTED" ]; then + if [ -n "$fps_expect" ]; then + DISPLAY_FPS_EXPECTED="$fps_expect" + else + DISPLAY_FPS_EXPECTED="$fps_default" + fi + fi + + DISPLAY_FPS_MIN_OK="$(awk -v f="$DISPLAY_FPS_EXPECTED" -v t="$fps_tol" 'BEGIN { printf "%.0f\n", f * (100.0 - t) / 100.0 }')" + DISPLAY_FPS_MAX_OK="$(awk -v f="$DISPLAY_FPS_EXPECTED" -v t="$fps_tol" 'BEGIN { printf "%.0f\n", f * (100.0 + t) / 100.0 }')" + + log_info "FPS policy: mode=fixed expected=${DISPLAY_FPS_EXPECTED} range=[${DISPLAY_FPS_MIN_OK}, ${DISPLAY_FPS_MAX_OK}]" + return 0 +} + +# Apply refresh policy for display tests. +# Fixed ~60 FPS target gets best-effort 60Hz normalization; detected mode keeps native refresh. +display_apply_fps_refresh_policy() { + if [ -z "${DISPLAY_FPS_MODE:-}" ] || [ -z "${DISPLAY_FPS_EXPECTED:-}" ]; then + log_warn "display_apply_fps_refresh_policy: FPS policy not resolved" + return 1 + fi + + if [ "$DISPLAY_FPS_MODE" = "detected" ]; then + log_info "Detected FPS mode selected; keeping native refresh" + return 0 + fi + + if hz_is_about_60 "${DISPLAY_FPS_EXPECTED}"; then + if command -v weston_force_primary_1080p60_if_not_60 >/dev/null 2>&1; then + log_info "Fixed ~60 FPS policy selected; ensuring primary output is ~60Hz (best-effort)" + if weston_force_primary_1080p60_if_not_60; then + log_info "Primary output is ~60Hz (or was already ~60Hz)" + else + log_warn "Unable to force ~60Hz (continuing; not a hard failure)" + fi + else + log_warn "weston_force_primary_1080p60_if_not_60 helper not found; skipping ~60Hz enforcement" + fi + else + log_info "Fixed FPS policy selected with expected=${DISPLAY_FPS_EXPECTED}; no refresh normalization applied" + fi + + return 0 +} + +# Gate measured FPS against the resolved display FPS policy. +# Returns 0 for pass, 1 for fail. Logs the reason internally. +display_fps_gate_avg() { + fps_avg="$1" + fps_count="$2" + require_fps="${REQUIRE_FPS:-1}" + + if [ "$require_fps" -eq 0 ]; then + if [ "$fps_count" -eq 0 ]; then + log_warn "REQUIRE_FPS=0 and no FPS samples found; skipping FPS gating" + else + log_info "REQUIRE_FPS=0; FPS stats recorded but not used for gating" + fi + return 0 + fi + + if [ "$fps_count" -eq 0 ]; then + log_fail "FPS gating enabled but no FPS samples were found" + return 1 + fi + + fps_int="$(printf '%s\n' "$fps_avg" | awk 'BEGIN {v=0} {v=$1+0.0} END {printf "%.0f\n", v}')" + + if [ "${DISPLAY_FPS_MODE:-}" = "detected" ]; then + if [ -z "${DISPLAY_FPS_MIN_OK:-}" ]; then + log_fail "Detected FPS policy missing minimum threshold" + return 1 + fi + + if [ "$fps_int" -lt "$DISPLAY_FPS_MIN_OK" ]; then + log_fail "Average FPS below detected-refresh threshold: avg=${fps_avg} (~${fps_int}) < ${DISPLAY_FPS_MIN_OK} (refresh=${DISPLAY_FPS_DETECTED_HZ}Hz)" + return 1 + fi + + log_info "Detected-refresh FPS gate passed: avg=${fps_avg} (~${fps_int}) >= ${DISPLAY_FPS_MIN_OK} (refresh=${DISPLAY_FPS_DETECTED_HZ}Hz)" + return 0 + fi + + if [ -z "${DISPLAY_FPS_MIN_OK:-}" ] || [ -z "${DISPLAY_FPS_MAX_OK:-}" ]; then + log_fail "Fixed FPS policy missing valid range" + return 1 + fi + + if [ "$fps_int" -lt "$DISPLAY_FPS_MIN_OK" ] || [ "$fps_int" -gt "$DISPLAY_FPS_MAX_OK" ]; then + 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})" + return 1 + fi + + log_info "Fixed FPS gate passed: avg=${fps_avg} (~${fps_int}) in [${DISPLAY_FPS_MIN_OK}, ${DISPLAY_FPS_MAX_OK}]" + return 0 +} + +# Parse FPS samples from a weston-simple-egl style log. +# Sets DISPLAY_FPS_COUNT / DISPLAY_FPS_AVG / DISPLAY_FPS_MIN / DISPLAY_FPS_MAX. +display_parse_fps_log() { + logf="$1" + + DISPLAY_FPS_COUNT=0 + DISPLAY_FPS_AVG="-" + DISPLAY_FPS_MIN="-" + DISPLAY_FPS_MAX="-" + + [ -n "$logf" ] || return 1 + [ -r "$logf" ] || return 1 + + fps_stats=$( + awk ' + /[0-9]+[[:space:]]+frames in[[:space:]]+[0-9]+[[:space:]]+seconds/ { + val = $(NF-1) + 0.0 + all_n++ + all_vals[all_n] = val + } + END { + if (all_n == 0) exit + + if (all_n == 1) { + n = 1 + sum = all_vals[1] + min = all_vals[1] + max = all_vals[1] + } else { + n = 0 + sum = 0.0 + for (i = 2; i <= all_n; i++) { + v = all_vals[i] + n++ + sum += v + if (n == 1 || v < min) min = v + if (n == 1 || v > max) max = v + } + } + + if (n > 0) { + avg = sum / n + printf "n=%d avg=%f min=%f max=%f\n", n, avg, min, max + } + } + ' "$logf" 2>/dev/null || true + ) + + [ -n "$fps_stats" ] || return 1 + + DISPLAY_FPS_COUNT=$(printf '%s\n' "$fps_stats" | awk '{print $1}' | sed 's/^n=//') + DISPLAY_FPS_AVG=$(printf '%s\n' "$fps_stats" | awk '{print $2}' | sed 's/^avg=//') + DISPLAY_FPS_MIN=$(printf '%s\n' "$fps_stats" | awk '{print $3}' | sed 's/^min=//') + DISPLAY_FPS_MAX=$(printf '%s\n' "$fps_stats" | awk '{print $4}' | sed 's/^max=//') + + case "$DISPLAY_FPS_COUNT" in ''|*[!0-9]*) DISPLAY_FPS_COUNT=0 ;; esac + [ -n "$DISPLAY_FPS_AVG" ] || DISPLAY_FPS_AVG="-" + [ -n "$DISPLAY_FPS_MIN" ] || DISPLAY_FPS_MIN="-" + [ -n "$DISPLAY_FPS_MAX" ] || DISPLAY_FPS_MAX="-" + + return 0 +}