mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Feat] (Trace): the replay runner builds as an adb-shell executable for Android, and unix endpoints carry a headless window
MOBILEGL_BUILD_TRACE_REPLAY now also produces mobilegl_trace_replay on ANDROID: the same CLI as desktop, linked against the APK runner's glws/glproc glue. On the device it dials a render server with no Activity at all - MOBILEGL_IPC_CONTROL=unix:@name with shm data to the offscreen supervisor (a cross-uid abstract connect needs root or an SELinux waiver; loopback TCP works from plain adb shell), or tcp:// with MOBILEGL_IPC_SURFACE=server to the on-screen display server. glws_android grows the desktop glws_egl's server-owned null-window createWindowSurface, gated on MOBILEGL_TRACE_SURFACE=window so the APK's pbuffer mode keeps its old answer, and the config carries EGL_WINDOW_BIT for it. The control screen refuses unix endpoints in on-screen mode: the in-process display server serves tcp:// only. Verified on-device with an OpenRA retrace, ssim=1.0 both ways: offscreen service on @mgl-cli with the CLI as root, and the display Activity on tcp://127.0.0.1:40613 with the replay's frames on the phone's screen.
This commit is contained in:
@@ -75,6 +75,14 @@ int ResolveHeight(int height) {
|
||||
return height > 0 ? height : 1;
|
||||
}
|
||||
|
||||
// A HEADLESS command-line replay (no ANativeWindow) that still wants a window surface: the
|
||||
// window will be the MobileGL server's (MOBILEGL_IPC_SURFACE=server), so the config must
|
||||
// carry EGL_WINDOW_BIT for the null-window eglCreateWindowSurface in createSurface.
|
||||
bool WantsServerOwnedWindow() {
|
||||
const char *mode = std::getenv("MOBILEGL_TRACE_SURFACE");
|
||||
return gNativeWindow == nullptr && mode != nullptr && std::strcmp(mode, "window") == 0;
|
||||
}
|
||||
|
||||
void *Lookup(const char *name) {
|
||||
if (gMobileGl == nullptr) {
|
||||
gMobileGl = dlopen("libMobileGL.so", RTLD_NOW | RTLD_GLOBAL | RTLD_NOLOAD);
|
||||
@@ -206,6 +214,22 @@ private:
|
||||
static_cast<const AndroidVisual *>(visual)->config,
|
||||
gNativeWindow,
|
||||
nullptr);
|
||||
} else if (!pbuffer && WantsServerOwnedWindow()) {
|
||||
// HEADLESS COMMAND-LINE REPLAY (P12 D9, same shape as the desktop glws_egl path):
|
||||
// the window is the MobileGL SERVER's (MOBILEGL_IPC_SURFACE=server,
|
||||
// WindowKind::ServerOwned), so the native window is none and the size the trace
|
||||
// wants rides EGL_WIDTH/EGL_HEIGHT. Gated on MOBILEGL_TRACE_SURFACE=window so the
|
||||
// APK's pbuffer mode (no ANativeWindow either) keeps its pbuffer.
|
||||
const EGLint windowAttribs[] = {
|
||||
EGL_WIDTH, surfaceWidth,
|
||||
EGL_HEIGHT, surfaceHeight,
|
||||
EGL_NONE,
|
||||
};
|
||||
surface = gEgl.createWindowSurface(
|
||||
gDisplay,
|
||||
static_cast<const AndroidVisual *>(visual)->config,
|
||||
EGLNativeWindowType{},
|
||||
windowAttribs);
|
||||
} else {
|
||||
const EGLint attribs[] = {
|
||||
EGL_WIDTH, surfaceWidth,
|
||||
@@ -334,7 +358,8 @@ Visual *createVisual(bool doubleBuffer, unsigned samples, Profile profile) {
|
||||
}
|
||||
|
||||
const EGLint attribs[] = {
|
||||
EGL_SURFACE_TYPE, gNativeWindow == nullptr ? EGL_PBUFFER_BIT : EGL_WINDOW_BIT,
|
||||
EGL_SURFACE_TYPE,
|
||||
gNativeWindow == nullptr && !WantsServerOwnedWindow() ? EGL_PBUFFER_BIT : EGL_WINDOW_BIT,
|
||||
EGL_RENDERABLE_TYPE,
|
||||
visual->api == EGL_OPENGL_ES_API ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_BIT,
|
||||
EGL_RED_SIZE, 8,
|
||||
|
||||
@@ -98,7 +98,7 @@ public final class ServerControlActivity extends Activity {
|
||||
envField = addField(contentLayout, "Extra env (optional)", "", dp(8));
|
||||
|
||||
onScreenBox = new CheckBox(this);
|
||||
onScreenBox.setText("On-screen window (render client frames onto this screen)");
|
||||
onScreenBox.setText("On-screen window (render client frames onto this screen; tcp:// only)");
|
||||
onScreenBox.setTextColor(COLOR_TEXT);
|
||||
onScreenBox.setTextSize(TypedValue.COMPLEX_UNIT_SP, 13);
|
||||
LinearLayout.LayoutParams boxParams = new LinearLayout.LayoutParams(
|
||||
@@ -155,6 +155,14 @@ public final class ServerControlActivity extends Activity {
|
||||
String token = tokenField.getText().toString();
|
||||
String env = envField.getText().toString().trim();
|
||||
|
||||
// The in-process display server only accepts tcp:// (ServerMain's in-process arm);
|
||||
// the unix forms belong to the offscreen supervisor.
|
||||
if (onScreenBox.isChecked() && !endpoint.startsWith("tcp://")) {
|
||||
setStatus("The on-screen display server serves tcp:// only; use a tcp:// endpoint "
|
||||
+ "or uncheck On-screen window.", COLOR_FAIL);
|
||||
return;
|
||||
}
|
||||
|
||||
String probeDisplay;
|
||||
Probe probe;
|
||||
if (endpoint.startsWith("tcp://")) {
|
||||
|
||||
Reference in New Issue
Block a user