gallery/scripts/build.sh
Greg Pomerantz ed52109dba GPU-resident thumbnails: worker uploads to Slint's wgpu device (gputex)
Root cause of scroll jank: first-present of each Image uploaded pixels
inside the render frame (~11-30 ms per 400px texture, 1.3 visible
hitches/s at 120 Hz; grey-image A/B: 20 -> 1). Slint has no render
thread and no pre-upload API.

Fix: decode worker creates the Rgba8Unorm texture on Slint's own wgpu
device (captured from GraphicsAPI::WGPU30 at RenderingSetup) and submits
the async upload; UI wraps it in Image::try_from(tex). Zero pixel work
in the render frame. CPU from_rgba8 fallback retained.

Measured (Pixel 9 Pro 120 Hz, 400 px, per-frame FR hook):
  before: >10ms renders 20 in 15s (max 30 ms), 3 borderline 8-9 ms
  after:  0 mid-scroll renders > 4.4 ms (median 1.9, p95 2.9);
          only post-idle first-frames expensive (invisible)

Also: FR per-frame logging via set_rendering_notifier; APLY timestamp.
2026-10-28 10:57:15 -04:00

78 lines
3.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# Build the gallery Android APK (and optionally install it).
#
# ./scripts/build.sh # release x86_64 (emulator) + install
# ./scripts/build.sh aarch64 # release aarch64 (real device) + install
# ./scripts/build.sh debug # debug x86_64 + install (faster builds)
# ./scripts/build.sh <arch> no-install
#
# Desktop (Linux): cargo run (needs libfontconfig1 + pkg-config)
# Desktop (macOS): cargo run (pure Rust, nothing extra)
set -euo pipefail
cd "$(dirname "$0")/.."
export ANDROID_HOME=$HOME/android-sdk
export ANDROID_NDK_ROOT=$HOME/android-sdk/ndk/27.0.12077973
# ~/.local/bin: nasm (host build of libjpeg-turbo SIMD; aarch64 needs no nasm).
export PATH="$HOME/.local/bin:$HOME/.cargo/bin:$ANDROID_HOME/platform-tools:$PATH"
# turbojpeg (M2): build the vendored libjpeg-turbo with CMake, statically linked
# into the app (no extra .so in the APK). The NDK CMake toolchain + ANDROID_*
# vars are picked up by the `cmake` crate; verified 2026-10 (HANDOFF §10).
if [ -n "$ANDROID_NDK_ROOT" ]; then
export CMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_ROOT/build/cmake/android.toolchain.cmake
export ANDROID_PLATFORM=android-26
export ANDROID_STL=c++_static
export TURBOJPEG_STATIC=1
fi
# SDK platform used to compile the Slint Java helper (target API, matches
# target_sdk_version in Cargo.toml). Must be an installed platform dir.
SDK_PLATFORM=android-35
# Slint's android-activity build reads ANDROID_JAR first; setting it explicitly
# lets us ALSO export ANDROID_PLATFORM=android-26 below (for the NDK CMake
# toolchain's native API level) without the two tools fighting over that
# variable (`android-build` would otherwise look up platforms/android-26).
export ANDROID_JAR=$ANDROID_HOME/platforms/$SDK_PLATFORM/android.jar
# C/C++ cross-compilers for bundled native deps (libsqlite3-sys via rusqlite).
# The `cc` crate picks these up per target triple (min sdk 26).
NDK_BIN=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin
# CMake target ABI (x86_64 default; overridden below for aarch64).
export ANDROID_ABI=x86_64
export CC_x86_64_linux_android=$NDK_BIN/x86_64-linux-android26-clang
export CXX_x86_64_linux_android=$NDK_BIN/x86_64-linux-android26-clang++
export AR_x86_64_linux_android=$NDK_BIN/llvm-ar
export CC_aarch64_linux_android=$NDK_BIN/aarch64-linux-android26-clang
export CXX_aarch64_linux_android=$NDK_BIN/aarch64-linux-android26-clang++
export AR_aarch64_linux_android=$NDK_BIN/llvm-ar
# Debug-keystore signing is fine for personal use / Play internal testing.
export CARGO_APK_RELEASE_KEYSTORE=$HOME/.android/debug.keystore
export CARGO_APK_RELEASE_KEYSTORE_PASSWORD=android
arg1=${1:-x86_64}
arg2=${2:-install}
profile=--release
case $arg1 in
debug) target=x86_64-linux-android; profile="" ;;
debug-aarch64) target=aarch64-linux-android; profile=""; export ANDROID_ABI=arm64-v8a ;;
x86_64) target=x86_64-linux-android ;;
aarch64) target=aarch64-linux-android; export ANDROID_ABI=arm64-v8a ;;
*) echo "unknown arch: $arg1" >&2; exit 1 ;;
esac
profile_dir=release; [ -z "$profile" ] && profile_dir=debug
# Optional: ADB_SERIAL picks the device when several are attached (see AGENTS.md).
adb=(); [ -n "${ADB_SERIAL:-}" ] && adb=(adb -s "$ADB_SERIAL")
cargo apk2 build $profile --target "$target" --lib
apk=target/$profile_dir/apk/gallery.apk
echo "APK: $apk ($(du -h "$apk" | cut -f1))"
if [ "$arg2" = install ] && command -v adb >/dev/null; then
"${adb[@]}" install -r "$apk"
"${adb[@]}" shell am start -n wow.gmp.gallery/android.app.NativeActivity || true
fi