nuclear@23: #include nuclear@23: #include nuclear@23: #include nuclear@23: #include nuclear@27: #include nuclear@23: #include "android_native_app_glue.h" nuclear@24: #include nuclear@23: #include nuclear@23: #include "logger.h" nuclear@23: #include "istereo.h" nuclear@23: nuclear@23: struct android_app *app; nuclear@23: nuclear@23: static void handle_command(struct android_app *app, int32_t cmd); nuclear@23: static int handle_input(struct android_app *app, AInputEvent *ev); nuclear@23: static int handle_touch_input(struct android_app *app, AInputEvent *ev); nuclear@23: static int init_gl(void); nuclear@23: static void destroy_gl(void); nuclear@23: nuclear@23: static EGLDisplay dpy; nuclear@23: static EGLSurface surf; nuclear@23: static EGLContext ctx; nuclear@23: nuclear@23: static int redisp_pending = 1; /* TODO stop busy-looping */ nuclear@23: nuclear@23: static int width, height; nuclear@23: static int init_done; nuclear@23: nuclear@27: static JavaVM *jvm; nuclear@27: static JNIEnv *jni; nuclear@27: static jclass activity_class; nuclear@27: nuclear@23: void android_main(struct android_app *app_ptr) nuclear@23: { nuclear@23: app_dummy(); nuclear@23: app = app_ptr; nuclear@23: nuclear@23: app->onAppCmd = handle_command; nuclear@23: app->onInputEvent = handle_input; nuclear@23: nuclear@24: //ANativeActivity_setWindowFlags(app->activity, AWINDOW_FLAG_FULLSCREEN, 0); nuclear@24: nuclear@23: start_logger(); nuclear@23: nuclear@27: jvm = app->activity->vm; nuclear@27: if((*jvm)->AttachCurrentThread(jvm, &jni, 0) != 0) { nuclear@27: fprintf(stderr, "failed to attach native thread to Java VM\n"); nuclear@27: exit(1); nuclear@27: } nuclear@27: activity_class = (*jni)->GetObjectClass(jni, app->activity->clazz); nuclear@27: nuclear@23: for(;;) { nuclear@23: int num_events; nuclear@23: struct android_poll_source *pollsrc; nuclear@23: nuclear@23: while(ALooper_pollAll(0, 0, &num_events, (void**)&pollsrc) >= 0) { nuclear@23: if(pollsrc) { nuclear@23: pollsrc->process(app, pollsrc); nuclear@23: } nuclear@23: } nuclear@23: nuclear@23: if(app->destroyRequested) { nuclear@23: return; nuclear@23: } nuclear@23: nuclear@23: if(init_done && redisp_pending) { nuclear@23: redraw(); nuclear@23: eglSwapBuffers(dpy, surf); nuclear@23: } nuclear@23: } nuclear@23: } nuclear@23: nuclear@23: void set_mouse_pos(int x, int y) nuclear@23: { nuclear@23: } nuclear@23: nuclear@23: void set_mouse_cursor(int enable) nuclear@23: { nuclear@23: } nuclear@23: nuclear@23: /* TODO */ nuclear@23: void ad_banner_show(void) nuclear@23: { nuclear@27: jmethodID method; nuclear@27: if(!jvm) return; nuclear@27: nuclear@27: if(!(method = (*jni)->GetMethodID(jni, activity_class, "show_ad", "()V"))) { nuclear@27: fprintf(stderr, "failed to retrieve MainActivity.show_ad method\n"); nuclear@27: return; nuclear@27: } nuclear@27: (*jni)->CallVoidMethod(jni, activity_class, method); nuclear@23: } nuclear@23: nuclear@23: void ad_banner_hide(void) nuclear@23: { nuclear@27: jmethodID method; nuclear@27: if(!jvm) return; nuclear@27: nuclear@27: if(!(method = (*jni)->GetMethodID(jni, activity_class, "hide_ad", "()V"))) { nuclear@27: fprintf(stderr, "failed to retrieve MainActivity.hide_ad method\n"); nuclear@27: return; nuclear@27: } nuclear@27: (*jni)->CallVoidMethod(jni, activity_class, method); nuclear@23: } nuclear@23: nuclear@23: static void handle_command(struct android_app *app, int32_t cmd) nuclear@23: { nuclear@23: switch(cmd) { nuclear@23: case APP_CMD_SAVE_STATE: nuclear@23: /* save the application state to be reloaded on restart if needed */ nuclear@23: break; nuclear@23: nuclear@23: case APP_CMD_INIT_WINDOW: nuclear@24: printf("APP_CMD_INIT_WINDOW\n"); nuclear@23: if(init_gl() == -1) { nuclear@23: exit(1); nuclear@23: } nuclear@23: /* initialize the application */ nuclear@23: if(init() == -1) { nuclear@23: exit(1); /* initialization failed, quit */ nuclear@23: } nuclear@24: reshape(width, height); nuclear@23: init_done = 1; nuclear@23: break; nuclear@23: nuclear@23: case APP_CMD_TERM_WINDOW: nuclear@23: /* cleanup */ nuclear@24: printf("APP_CMD_TERM_WINDOW\n"); nuclear@23: init_done = 0; nuclear@23: cleanup(); nuclear@23: destroy_gl(); nuclear@23: break; nuclear@23: nuclear@23: case APP_CMD_GAINED_FOCUS: nuclear@24: printf("APP_CMD_GAINED_FOCUS\n"); nuclear@23: /* app focused */ nuclear@23: break; nuclear@23: nuclear@23: case APP_CMD_LOST_FOCUS: nuclear@24: printf("APP_CMD_LOST_FOCUS\n"); nuclear@23: /* app lost focus */ nuclear@23: break; nuclear@23: nuclear@23: case APP_CMD_WINDOW_RESIZED: nuclear@23: case APP_CMD_CONFIG_CHANGED: nuclear@23: { nuclear@23: int nx = ANativeWindow_getWidth(app->window); nuclear@23: int ny = ANativeWindow_getHeight(app->window); nuclear@23: if(nx != width || ny != height) { nuclear@24: printf("reshape(%d, %d)\n", nx, ny); nuclear@23: reshape(nx, ny); nuclear@23: width = nx; nuclear@23: height = ny; nuclear@23: } nuclear@23: } nuclear@23: break; nuclear@23: nuclear@23: default: nuclear@23: break; nuclear@23: } nuclear@23: } nuclear@23: nuclear@23: static int handle_input(struct android_app *app, AInputEvent *ev) nuclear@23: { nuclear@23: int evtype = AInputEvent_getType(ev); nuclear@23: nuclear@23: switch(evtype) { nuclear@23: case AINPUT_EVENT_TYPE_MOTION: nuclear@23: return handle_touch_input(app, ev); nuclear@23: nuclear@23: default: nuclear@23: break; nuclear@23: } nuclear@23: return 0; nuclear@23: } nuclear@23: nuclear@23: #define MAX_TOUCH_IDS 32 nuclear@23: nuclear@23: static int handle_touch_input(struct android_app *app, AInputEvent *ev) nuclear@23: { nuclear@23: int x, y, idx, touch_id; nuclear@23: unsigned int action; nuclear@23: static int prev_pos[MAX_TOUCH_IDS][2]; nuclear@23: nuclear@23: action = AMotionEvent_getAction(ev); nuclear@23: nuclear@23: idx = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> nuclear@23: AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; nuclear@23: touch_id = AMotionEvent_getPointerId(ev, idx); nuclear@23: nuclear@23: x = AMotionEvent_getX(ev, idx); nuclear@23: y = AMotionEvent_getY(ev, idx); nuclear@23: nuclear@23: switch(action & AMOTION_EVENT_ACTION_MASK) { nuclear@23: case AMOTION_EVENT_ACTION_DOWN: nuclear@23: case AMOTION_EVENT_ACTION_POINTER_DOWN: nuclear@23: if(touch_id == 0) { nuclear@23: mouse_button(0, 1, x, y); nuclear@23: } nuclear@23: if(touch_id < MAX_TOUCH_IDS) { nuclear@23: prev_pos[touch_id][0] = x; nuclear@23: prev_pos[touch_id][1] = y; nuclear@23: } nuclear@23: break; nuclear@23: nuclear@23: case AMOTION_EVENT_ACTION_UP: nuclear@23: case AMOTION_EVENT_ACTION_POINTER_UP: nuclear@23: if(touch_id == 0) { nuclear@23: mouse_button(0, 0, x, y); nuclear@23: } nuclear@23: if(touch_id < MAX_TOUCH_IDS) { nuclear@23: prev_pos[touch_id][0] = x; nuclear@23: prev_pos[touch_id][1] = y; nuclear@23: } nuclear@23: break; nuclear@23: nuclear@23: case AMOTION_EVENT_ACTION_MOVE: nuclear@23: { nuclear@23: int i, pcount = AMotionEvent_getPointerCount(ev); nuclear@23: for(i=0; iwindow, 0, 0, vis); nuclear@23: nuclear@23: if(!(surf = eglCreateWindowSurface(dpy, eglcfg, app->window, 0))) { nuclear@23: fprintf(stderr, "failed to create window\n"); nuclear@23: destroy_gl(); nuclear@23: return -1; nuclear@23: } nuclear@23: nuclear@23: if(!(ctx = eglCreateContext(dpy, eglcfg, EGL_NO_CONTEXT, ctxattr))) { nuclear@23: fprintf(stderr, "failed to create OpenGL ES context\n"); nuclear@23: destroy_gl(); nuclear@23: return -1; nuclear@23: } nuclear@23: eglMakeCurrent(dpy, surf, surf, ctx); nuclear@23: nuclear@23: eglQuerySurface(dpy, surf, EGL_WIDTH, &width); nuclear@23: eglQuerySurface(dpy, surf, EGL_HEIGHT, &height); nuclear@24: printf("initial reshape call: %dx%d\n", width, height); nuclear@23: reshape(width, height); nuclear@23: nuclear@23: return 0; nuclear@23: } nuclear@23: nuclear@23: static void destroy_gl(void) nuclear@23: { nuclear@23: if(!dpy) return; nuclear@23: nuclear@23: eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); nuclear@23: nuclear@23: if(ctx) { nuclear@23: eglDestroyContext(dpy, ctx); nuclear@23: ctx = 0; nuclear@23: } nuclear@23: if(surf) { nuclear@23: eglDestroySurface(dpy, surf); nuclear@23: surf = 0; nuclear@23: } nuclear@23: nuclear@23: eglTerminate(dpy); nuclear@23: dpy = 0; nuclear@23: }