// Android-only: pure-sx NativeActivity that brings up EGL on the // ANativeWindow delivered by native_app_glue and clears the screen // every frame via GLES3. Equivalent of `examples/63-metal-clear.sx` // for the Android target. // // Entry-point contract (the "via Platform" shape): // - User writes BOTH `main` and `android_main` at top level. // - `android_main(app)` calls `sx_android_bootstrap(app)` and then // `main()`. The library never names `main`; the OS-shape entry // symbol lives in user code, where the other entry symbols are. // - `main` instantiates `AndroidPlatform`, calls `init`, then // `run_frame_loop` which drives the looper until destroyRequested. // // This exercises end-to-end the Android pipeline shipped in Session 70: // - `sx build --target android` toolchain (NDK clang + glue link). // - `--apk` APK assembly (manifest + aapt2 + zipalign + apksigner). // - `android_main` (user-written here) gets external LLVM linkage // via the `isExportedEntryName` allowlist in lower.zig. // - `AndroidPlatform.run_frame_loop` drains ALooper events, // creates EGL on `APP_CMD_INIT_WINDOW`, ticks the closure every // 16 ms. // // Build + install on a connected device: // // /Users/agra/projects/sx/zig-out/bin/sx build --target android \ // --apk /tmp/sxhello.apk --bundle-id co.swipelab.sxhello \ // -o /tmp/libsxhello.so examples/99-android-egl-clear.sx // adb install -r /tmp/sxhello.apk // adb shell am start -n co.swipelab.sxhello/android.app.NativeActivity // adb logcat -d --pid=$(adb shell pidof co.swipelab.sxhello) // // Expected: solid purple frame on the device. Periodic // `rendered 60 frames` lines in logcat. #import "modules/std.sx"; #import "modules/compiler.sx"; #import "modules/platform/api.sx"; #import "modules/platform/android.sx"; // GLES3 (linked via -lGLESv3) glClearColor :: (r: f32, g: f32, b: f32, a: f32) #foreign; glClear :: (mask: u32) #foreign; GL_COLOR_BUFFER_BIT :u32: 0x4000; frame_count : s32 = 0; g_plat : *AndroidPlatform = null; frame_tick :: () { fc := g_plat.begin_frame(); glClearColor(0.5, 0.2, 0.8, 1.0); // purple glClear(GL_COLOR_BUFFER_BIT); g_plat.end_frame(); frame_count += 1; if (frame_count % 60) == 0 { __android_log_print(4, "sxhello".ptr, "rendered 60 frames\n".ptr); } } main :: () -> s32 { inline if OS == .android { plat : AndroidPlatform = .{}; plat.init("sxhello", 0, 0); g_plat = @plat; plat.run_frame_loop(() => frame_tick()); } 0; } // OS-shape entry symbol. native_app_glue's // `ANativeActivity_onCreate` ultimately calls this on the worker // thread. We hand the app pointer to the platform module and then // let user `main` drive the normal cross-platform setup path. android_main :: (app: *void) { inline if OS == .android { sx_android_bootstrap(app); main(); } }