diff --git a/android-plugin/TRACE_REPLAY.md b/android-plugin/TRACE_REPLAY.md index 9aca0a21..923ce085 100644 --- a/android-plugin/TRACE_REPLAY.md +++ b/android-plugin/TRACE_REPLAY.md @@ -38,6 +38,7 @@ crop_y optional compare crop y crop_width optional compare crop width crop_height optional compare crop height use_angle optional boolean; DirectGLES uses packaged ANGLE when true +use_pbuffer optional boolean; DirectGLES uses an offscreen EGL pbuffer when true angle_library_dir optional directory containing libEGL_angle.so and libGLESv2_angle.so; defaults to the APK native library directory ``` @@ -46,10 +47,10 @@ Implementation notes: - The trace APK builds independently from FCL and can be launched with `adb shell am start`. - The native runner validates inputs, sets `MOBILEGL_BACKEND_TYPE`, loads `libMobileGL.so`, runs apitrace GL retrace, writes `actual.png`, and writes `result.json`. - The runner uses a MobileGL-backed EGL window-system shim. GLX calls in PC traces are consumed by apitrace's GLX retrace frontend and mapped onto this EGL shim; the Android runner does not require or call a MobileGL GLX implementation. -- `DirectGLES` replays on an EGL pbuffer by default, avoiding Android `SurfaceView` lifetime coupling. `DirectVulkan` still uses the Activity surface because it needs a native window-backed Vulkan swapchain. +- `DirectGLES` and `DirectVulkan` replay on the Activity `SurfaceView` by default. DirectGLES can still use the old offscreen EGL pbuffer path by passing `use_pbuffer=true`. - Golden comparison is implemented in native C++ with libpng RGBA decode and SSIM validation. The Java Activity only passes arguments and displays the native result, so the replay/compare core is not tied to Android UI or Bitmap APIs and can be ported to Linux. - The plugin profile still excludes `libtrace_replay_runner.so`; normal plugin APK behavior is preserved. -- Set `MOBILEGL_RETRACE_USE_ANGLE=1` when running `trace-replay-ci.sh` to pass `use_angle=true` for DirectGLES. The APK must include `libEGL_angle.so` and `libGLESv2_angle.so` under its x86_64 native libraries. The Activity passes Android's `nativeLibraryDir` to native code as `MOBILEGL_RETRACE_ANGLE_DIR`. +- Set `MOBILEGL_RETRACE_USE_ANGLE=1` when running `trace-replay-ci.sh` to pass `use_angle=true` for DirectGLES. Set `MOBILEGL_RETRACE_USE_PBUFFER=1` or pass `--use-pbuffer` to keep DirectGLES offscreen. The APK must include `libEGL_angle.so` and `libGLESv2_angle.so` under its x86_64 native libraries. The Activity passes Android's `nativeLibraryDir` to native code as `MOBILEGL_RETRACE_ANGLE_DIR`. Example core-profile trace smoke command for a debug trace APK: diff --git a/android-plugin/app/src/trace/cpp/trace_replay_core.cpp b/android-plugin/app/src/trace/cpp/trace_replay_core.cpp index 7d25bf81..04edea5f 100644 --- a/android-plugin/app/src/trace/cpp/trace_replay_core.cpp +++ b/android-plugin/app/src/trace/cpp/trace_replay_core.cpp @@ -814,6 +814,7 @@ bool WriteResultJson(const Request& request, const Result& result) { file << " \"ssim\": " << result.ssim << ",\n"; file << " \"ssimThreshold\": " << request.ssimThreshold << ",\n"; file << " \"useAngle\": " << (UseAngleForRequest(request) ? "true" : "false") << ",\n"; + file << " \"usePbuffer\": " << (request.usePbuffer ? "true" : "false") << ",\n"; file << " \"mismatchPixels\": " << result.mismatchPixels << "\n"; file << "}\n"; return true; diff --git a/android-plugin/app/src/trace/cpp/trace_replay_core.hpp b/android-plugin/app/src/trace/cpp/trace_replay_core.hpp index ac1aade7..1b48dbf6 100644 --- a/android-plugin/app/src/trace/cpp/trace_replay_core.hpp +++ b/android-plugin/app/src/trace/cpp/trace_replay_core.hpp @@ -34,6 +34,7 @@ struct Request { int cropHeight = 0; double ssimThreshold = 0.99; bool useAngle = false; + bool usePbuffer = false; }; struct Result { diff --git a/android-plugin/app/src/trace/cpp/trace_replay_jni.cpp b/android-plugin/app/src/trace/cpp/trace_replay_jni.cpp index 4b759df2..d7ea89a2 100644 --- a/android-plugin/app/src/trace/cpp/trace_replay_jni.cpp +++ b/android-plugin/app/src/trace/cpp/trace_replay_jni.cpp @@ -99,7 +99,8 @@ Java_top_mobilegl_plugin_trace_TraceReplayActivity_nativeRunTraceReplay(JNIEnv* jint cropWidth, jint cropHeight, jstring angleLibraryDir, - jboolean useAngle) { + jboolean useAngle, + jboolean usePbuffer) { mobilegl_trace::Request request; request.tracePath = ToString(env, tracePath); request.goldenPath = ToString(env, goldenPath); @@ -121,10 +122,13 @@ Java_top_mobilegl_plugin_trace_TraceReplayActivity_nativeRunTraceReplay(JNIEnv* request.cropWidth = cropWidth; request.cropHeight = cropHeight; request.useAngle = useAngle == JNI_TRUE; + request.usePbuffer = usePbuffer == JNI_TRUE; ScopedTraceReplayState replayState; mobilegl_trace_set_requested_size(request.width, request.height); - const bool needsNativeWindow = request.backend == "DirectVulkan"; + const bool needsNativeWindow = + request.backend == "DirectVulkan" || + (request.backend == "DirectGLES" && !request.usePbuffer); ANativeWindow *window = needsNativeWindow && surface != nullptr ? ANativeWindow_fromSurface(env, surface) : nullptr; mobilegl_trace_set_native_window(window); if (window != nullptr) { diff --git a/android-plugin/app/src/trace/java/top/mobilegl/plugin/trace/TraceReplayActivity.java b/android-plugin/app/src/trace/java/top/mobilegl/plugin/trace/TraceReplayActivity.java index 13ba2317..b033a811 100644 --- a/android-plugin/app/src/trace/java/top/mobilegl/plugin/trace/TraceReplayActivity.java +++ b/android-plugin/app/src/trace/java/top/mobilegl/plugin/trace/TraceReplayActivity.java @@ -112,7 +112,8 @@ public final class TraceReplayActivity extends Activity { request.cropWidth, request.cropHeight, request.angleLibraryDir, - request.useAngle + request.useAngle, + request.usePbuffer ); Log.i(TAG, result.toString()); TraceReplayResult finalResult = result; @@ -140,7 +141,8 @@ public final class TraceReplayActivity extends Activity { int cropWidth, int cropHeight, String angleLibraryDir, - boolean useAngle + boolean useAngle, + boolean usePbuffer ); private static final class TraceReplayRequest { @@ -161,6 +163,7 @@ public final class TraceReplayActivity extends Activity { final int cropHeight; final String angleLibraryDir; final boolean useAngle; + final boolean usePbuffer; private TraceReplayRequest( String tracePath, @@ -179,7 +182,8 @@ public final class TraceReplayActivity extends Activity { int cropWidth, int cropHeight, String angleLibraryDir, - boolean useAngle + boolean useAngle, + boolean usePbuffer ) { this.tracePath = tracePath; this.goldenPath = goldenPath; @@ -198,6 +202,7 @@ public final class TraceReplayActivity extends Activity { this.cropHeight = cropHeight; this.angleLibraryDir = angleLibraryDir; this.useAngle = useAngle; + this.usePbuffer = usePbuffer; } static TraceReplayRequest from(Intent intent, File filesDir, String nativeLibraryDir, String defaultBackend) { @@ -220,7 +225,8 @@ public final class TraceReplayActivity extends Activity { intent.getIntExtra("crop_width", 0), intent.getIntExtra("crop_height", 0), readString(intent, "angle_library_dir", nativeLibraryDir), - intent.getBooleanExtra("use_angle", false) + intent.getBooleanExtra("use_angle", false), + intent.getBooleanExtra("use_pbuffer", false) ); } diff --git a/android-plugin/trace-replay-ci.sh b/android-plugin/trace-replay-ci.sh index 85d15ff5..66a7d656 100644 --- a/android-plugin/trace-replay-ci.sh +++ b/android-plugin/trace-replay-ci.sh @@ -26,10 +26,13 @@ Usage: --crop-y N \ --crop-width N \ --crop-height N \ + [--use-pbuffer] \ --timeout-seconds N Set MOBILEGL_RETRACE_USE_ANGLE=1 to run DirectGLES replay with packaged ANGLE instead of the device system GLES driver. +Set MOBILEGL_RETRACE_USE_PBUFFER=1 or pass --use-pbuffer to run DirectGLES +against an offscreen EGL pbuffer instead of the Activity surface. EOF } @@ -72,6 +75,7 @@ crop_x="" crop_y="" crop_width="" crop_height="" +use_pbuffer=0 timeout_seconds="" while [ "$#" -gt 0 ]; do @@ -102,6 +106,7 @@ while [ "$#" -gt 0 ]; do --crop-y) crop_y="$(next_arg "$@")"; shift 2 ;; --crop-width) crop_width="$(next_arg "$@")"; shift 2 ;; --crop-height) crop_height="$(next_arg "$@")"; shift 2 ;; + --use-pbuffer) use_pbuffer=1; shift 1 ;; --timeout-seconds) timeout_seconds="$(next_arg "$@")"; shift 2 ;; -h|--help) usage; exit 0 ;; *) die "unknown argument: $1" ;; @@ -201,6 +206,9 @@ run_retrace() { if [ "${MOBILEGL_RETRACE_USE_ANGLE:-}" = "1" ] && [ "${backend}" = "DirectGLES" ]; then use_angle=1 fi + if [ "${MOBILEGL_RETRACE_USE_PBUFFER:-}" = "1" ] && [ "${backend}" = "DirectGLES" ]; then + use_pbuffer=1 + fi mkdir -p "${result_dir}" "${ADB}" install -r "${apk_file}" @@ -217,6 +225,9 @@ run_retrace() { if [ "${use_angle}" -eq 1 ]; then set -- "$@" --ez use_angle true fi + if [ "${use_pbuffer}" -eq 1 ] && [ "${backend}" = "DirectGLES" ]; then + set -- "$@" --ez use_pbuffer true + fi set -- "$@" \ --es output_dir "${app_dir}/output" \ --es diff_path "${app_dir}/output/${safe_case}-diff.png" \ diff --git a/tools/trace_replay/README.md b/tools/trace_replay/README.md index 4dce83f8..ff6160e0 100644 --- a/tools/trace_replay/README.md +++ b/tools/trace_replay/README.md @@ -152,3 +152,5 @@ adb exec-out run-as $PKG cat files/trace-replay/output/openra-diff.png > openra- For the Vulkan backend, build and install `:app:assembleMagmaTraceDebug`, set `PKG=top.mobilegl.plugin.magma.trace`, and pass `--es backend DirectVulkan`. +DirectGLES also renders to the Activity surface by default; pass +`--ez use_pbuffer true` to use the offscreen pbuffer path.