140 lines
4.8 KiB
Bash
Executable file
140 lines
4.8 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
|
|
# See LICENSE.md for license information.
|
|
# SPDX-License-Identifier: MIT
|
|
#
|
|
# verify-be-display.sh - Display parity gate for a Be API port (haiku,
|
|
# haiku32, beos): what the window shows must be the stage, at every window
|
|
# scale and on the full screen.
|
|
#
|
|
# The golden hashes gate the stage, never the display. The Be backend copies
|
|
# into its bitmap, and draws, only the rectangles that changed at each show,
|
|
# so a stale or misplaced rectangle would never reach a hash. UBER's probe
|
|
# build (make <port> builds it, into build/<port>/probe) ends with P13, the
|
|
# battery the other display gates run, which after every step asks the
|
|
# backend (jlHostBeProbeDisplayMismatch in src/hosted/be/beBackend.cpp) how many
|
|
# pixels differ: the frame's against the stage, the bitmap's against the
|
|
# frame, and the window as the shows left it against the window fully
|
|
# repainted, both read back from the screen (BScreen::ReadBitmap). Every
|
|
# count must be 0, and every pixel must have been compared: 64000 twice,
|
|
# plus the window's (the size the probe logs).
|
|
#
|
|
# One VM boot (scripts/lib/beGate.sh) runs UBERPROB once a spec, with
|
|
# JOEYLIB_SCALE / JOEYLIB_ASPECT / JOEYLIB_FULLSCREEN set as it asks.
|
|
#
|
|
# Usage: scripts/verify-be-display.sh [haiku|haiku32|beos] [SCALE[:square] | full]...
|
|
# (default haiku; specs 1:square 2:square 3 full)
|
|
# Requires: QEMU and the port's VM (install.sh install emulator:<port>);
|
|
# build/<port>/probe/UBERPROB (make <port>).
|
|
|
|
set -uo pipefail
|
|
|
|
repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
|
source "$repo/scripts/lib/joeyEnv.sh"
|
|
source "$repo/scripts/lib/beGate.sh"
|
|
|
|
port=${1:-haiku}
|
|
shift || true
|
|
label="verify-be-display ($port)"
|
|
beNeed "$port"
|
|
program=$repo/build/$port/probe/UBERPROB
|
|
probeLine="UBER-PROBE: beDisplayMismatch"
|
|
sizeLine="UBER-PROBE: beWindow"
|
|
doneLine="UBER: press any key to exit"
|
|
stagePixels=$((320 * 200))
|
|
fullSpec=full
|
|
bootSeconds=120
|
|
runSeconds=120 # one probe run, start to done line
|
|
defaults=(1:square 2:square 3 "$fullSpec")
|
|
specs=("$@")
|
|
[ ${#specs[@]} -gt 0 ] || specs=("${defaults[@]}")
|
|
|
|
[ -x "$program" ] || { echo "$label: the probe build is missing; run: make $port" >&2; exit 2; }
|
|
|
|
work=$(mktemp -d -t joeylib-be-display.XXXXXX)
|
|
cleanup() {
|
|
beStop
|
|
rm -rf "$work"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
# The job: each spec's run in a subshell of its own (its folder and
|
|
# settings stay there), its log kept as log<N>.txt.
|
|
mkdir -p "$work/job/UBERPROB"
|
|
cp "$program" "$work/job/UBERPROB/UBERPROB"
|
|
: > "$work/job/job.sh"
|
|
n=0
|
|
for spec in "${specs[@]}"; do
|
|
if [ "$spec" = "$fullSpec" ]; then
|
|
settings=(JOEYLIB_FULLSCREEN=1)
|
|
elif [[ "$spec" =~ ^([0-9]+)(:square)?$ ]]; then
|
|
settings=(JOEYLIB_SCALE="${BASH_REMATCH[1]}")
|
|
[ -n "${BASH_REMATCH[2]}" ] && settings+=(JOEYLIB_ASPECT=square)
|
|
else
|
|
echo "$label: bad spec \"$spec\" (SCALE[:square] or $fullSpec)" >&2
|
|
exit 2
|
|
fi
|
|
{
|
|
printf '(\n'
|
|
printf 'rm -f UBERPROB/joeylog.txt\n'
|
|
beJobScript UBERPROB UBERPROB "$doneLine" "$runSeconds" "${settings[@]}"
|
|
printf ')\n'
|
|
printf 'cp UBERPROB/joeylog.txt log%s.txt\n' "$n"
|
|
} >> "$work/job/job.sh"
|
|
n=$((n + 1))
|
|
done
|
|
beJobDisk "$work/job.img" "$work/job"
|
|
beStart "$work" "$work/job.img"
|
|
if ! beWaitJob "$work" "$bootSeconds"; then
|
|
echo "$label: FAIL - the VM did not start the job within ${bootSeconds} s" >&2
|
|
exit 1
|
|
fi
|
|
if ! beWaitExit "$work" "$((runSeconds * ${#specs[@]} + 60))"; then
|
|
echo "$label: FAIL - the runs did not finish" >&2
|
|
exit 1
|
|
fi
|
|
|
|
fails=""
|
|
passed=0
|
|
|
|
|
|
# fail SPEC WHAT -- note a failed run; the gate goes on with the rest.
|
|
fail() {
|
|
echo "$label: FAIL - $1: $2"
|
|
fails="${fails:+$fails; }$1"
|
|
}
|
|
|
|
|
|
n=0
|
|
for spec in "${specs[@]}"; do
|
|
log=$work/log$n.txt
|
|
n=$((n + 1))
|
|
beJobGet "$work/job.img" "log$((n - 1)).txt" "$log" || true
|
|
row=$(grep -F "$probeLine" "$log" 2> /dev/null | tr -d '\r' | tail -1)
|
|
size=$(grep -F "$sizeLine" "$log" 2> /dev/null | tr -d '\r' | tail -1)
|
|
if [ -z "$row" ] || [ -z "$size" ]; then
|
|
fail "$spec" "no \"$probeLine\" line"
|
|
continue
|
|
fi
|
|
size=${size#*"$sizeLine" }
|
|
w=${size%x*}
|
|
h=${size#*x}
|
|
want=$((2 * stagePixels + w * h))
|
|
counts=${row#*"$probeLine" }
|
|
echo "$label: $spec (${w}x${h}): $counts"
|
|
bad=$(printf '%s\n' "$counts" | tr ' ' '\n' | grep '^after' | grep -v '=0$' | tr '\n' ' ')
|
|
compared=$(printf '%s\n' "$counts" | sed -n 's/.*compared=\([0-9]*\).*/\1/p')
|
|
if [ -n "$bad" ]; then
|
|
fail "$spec" "pixels differ: $bad"
|
|
elif [ "$compared" != "$want" ]; then
|
|
fail "$spec" "compared $compared, want $want"
|
|
else
|
|
passed=$((passed + 1))
|
|
fi
|
|
done
|
|
|
|
if [ -n "$fails" ]; then
|
|
echo "$label: FAIL - $fails"
|
|
exit 1
|
|
fi
|
|
echo "$label: PASS ($passed window sizes: every pixel shown matches the stage after every present)"
|