diff options
| author | Arslaan Pathan <[email protected]> | 2026-08-13 19:10:04 +1200 |
|---|---|---|
| committer | Arslaan Pathan <[email protected]> | 2026-08-13 19:10:04 +1200 |
| commit | 93d033a3c6734cf92c32b2219bbb9f8e3aea55bf (patch) | |
| tree | 0e362221c8d654b02ca22d04ac2b6e8b82d9fcaf /jni/main.c | |
| parent | c5b510b532ec9464995726ca02288c5edf0d6d2b (diff) | |
| download | moku-assistant-93d033a3c6734cf92c32b2219bbb9f8e3aea55bf.tar.xz moku-assistant-93d033a3c6734cf92c32b2219bbb9f8e3aea55bf.zip | |
Work on making a proper event loop and implementing more of the engine
Diffstat (limited to 'jni/main.c')
| -rw-r--r-- | jni/main.c | 132 |
1 files changed, 131 insertions, 1 deletions
@@ -1,17 +1,147 @@ #include <android_native_app_glue.h> #include <android/log.h> +#include <android/sensor.h> +#include <stdint.h> +#include <stdlib.h> +#include <inttypes.h> +#include <string.h> +#include <android/native_window.h> +#include <android/set_abort_message.h> +#include <android/choreographer.h> +#include <android/hardware_buffer.h> +#include <time.h> + +#define LOG_TAG "moku" + +#define _LOG(priority, fmt, ...) \ + ((void)__android_log_print((priority), (LOG_TAG), \ + (fmt)__VA_OPT__(, ) __VA_ARGS__)) + +#define LOGE(fmt, ...) _LOG(ANDROID_LOG_ERROR, (fmt)__VA_OPT__(, ) __VA_ARGS__) +#define LOGW(fmt, ...) _LOG(ANDROID_LOG_WARN, (fmt)__VA_OPT__(, ) __VA_ARGS__) +#define LOGI(fmt, ...) _LOG(ANDROID_LOG_INFO, (fmt)__VA_OPT__(, ) __VA_ARGS__) + +enum Color { + COLOR_RED = 0x000000ff, + COLOR_GREEN = 0x0000ff00, + COLOR_BLUE = 0x00ff0000 +}; + +struct engine { + struct android_app *app; + int window_initialized; + int running; + int color; + uint64_t last_update; +}; + +struct engine *engine_new(struct android_app* app) { + struct engine engine; + + memset(&engine, 0, sizeof(engine)); + engine.window_initialized = 0; + engine.app = app; + engine.running = 0; + engine.color = 0; + engine.last_update = (uint64_t)0; +} + +uint64_t get_timestamp_ns() { + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + return (uint64_t)ts.tv_nsec + (uint64_t)ts.tv_sec * 1000000000; +} + +static void engine_schedule_tick(struct engine *engine); + +static void engine_real_tick(struct engine *engine) { + if (!engine->running) return; + + engine_schedule_tick(engine); +} + +static void engine_tick(long frameTimeNanos, void *data) { + struct engine *engine; + + if (!data) return; + engine = (struct engine*)data; + + engine_real_tick(engine); +} + +static void engine_schedule_tick(struct engine *engine) { + AChoreographer_postFrameCallback(AChoreographer_getInstance(), engine_tick, (void*)engine); +} + +/* TODO implement these stubs */ +void engine_attach_window(struct engine *engine) { + if (ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM) < 0) { + engine->window_initialized = 0; + return; + } + engine->window_initialized = 1; + engine->color = COLOR_RED; + engine->last_update = get_timestamp_ns(); +}; + +void engine_detach_window(struct engine *engine) { + /* Called when native window for app is destroyed. + * Doesn't mean app is being killed, also happens on rotate + * Normally, with a traditional OpenGL app, do cleanup here + * At the moment, it's fine to just set a flag to disable the rendering loop + */ + engine->window_initialized = 0; +}; + +void engine_resume(struct engine *engine) { + if (!engine->running) { + engine->running = 1; + engine_schedule_tick(engine); + } +}; + + +void engine_pause(struct engine *engine) { + +}; + +static void engine_handle_cmd(struct android_app *app, int32_t cmd) { + struct engine *engine; + + engine = (struct engine *)app->userData; + + switch (cmd) { + case APP_CMD_INIT_WINDOW: + engine_attach_window(engine); + break; + case APP_CMD_TERM_WINDOW: + engine_detach_window(engine); + break; + case APP_CMD_GAINED_FOCUS: + engine_resume(engine); + break; + case APP_CMD_LOST_FOCUS: + engine_pause(engine); + break; + } +} void android_main(struct android_app *state) { /* Declarations */ struct android_poll_source *source; + struct engine engine; int events; /* Code starts here */ app_dummy(); + memset(&engine, 0, sizeof(engine)); + state->userData = &engine; + state->onAppCmd = engine_handle_cmd; + /* do stuff here */ - while (1) { + while (!state->destroyRequested) { if (ALooper_pollAll(-1, NULL, &events, (void**)&source) >= 0) { if (source) { source->process(state, source); |
