nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include "app.h" nuclear@0: #include "logger.h" nuclear@0: nuclear@0: static void handle_command(struct android_app *app, int32_t cmd); nuclear@0: static int handle_input(struct android_app *app, AInputEvent *ev); nuclear@0: static int handle_touch_input(struct android_app *app, AInputEvent *ev); nuclear@0: static int init_gl(void); nuclear@0: static void destroy_gl(void); nuclear@0: nuclear@0: static struct android_app *app; nuclear@0: static int win_width, win_height; nuclear@0: nuclear@0: void android_main(struct android_app *app_ptr) nuclear@0: { nuclear@0: app_dummy(); nuclear@0: app = app_ptr; nuclear@0: nuclear@0: app->onAppCmd = handle_command; nuclear@0: app->onInputEvent = handle_input; nuclear@0: nuclear@0: start_logger(); nuclear@0: nuclear@0: for(;;) { nuclear@0: int num_events; nuclear@0: struct android_poll_source *pollsrc; nuclear@0: nuclear@0: while(ALooper_pollAll(0, 0, &num_events, (void**)&pollsrc) >= 0) { nuclear@0: if(pollsrc) { nuclear@0: pollsrc->process(app, pollsrc); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: if(app->destroyRequested) { nuclear@0: return; nuclear@0: } nuclear@0: nuclear@0: app_display(); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: static void handle_command(struct android_app *app, int32_t cmd) nuclear@0: { nuclear@0: switch(cmd) { nuclear@0: case APP_CMD_SAVE_STATE: nuclear@0: /* save the application state to be reloaded on restart if needed */ nuclear@0: break; nuclear@0: nuclear@0: case APP_CMD_INIT_WINDOW: nuclear@0: if(init_gl() == -1) { nuclear@0: exit(1); nuclear@0: } nuclear@0: /* initialize the application */ nuclear@0: if(app_init() == -1) { nuclear@0: exit(1); /* initialization failed, quit */ nuclear@0: } nuclear@0: break; nuclear@0: nuclear@0: case APP_CMD_TERM_WINDOW: nuclear@0: /* cleanup */ nuclear@0: app_cleanup(); nuclear@0: destroy_gl(); nuclear@0: break; nuclear@0: nuclear@0: case APP_CMD_GAINED_FOCUS: nuclear@0: /* app focused */ nuclear@0: break; nuclear@0: nuclear@0: case APP_CMD_LOST_FOCUS: nuclear@0: /* app lost focus */ nuclear@0: break; nuclear@0: nuclear@0: case APP_CMD_WINDOW_RESIZED: nuclear@0: case APP_CMD_CONFIG_CHANGED: nuclear@0: { nuclear@0: int nx = ANativeWindow_getWidth(app->window); nuclear@0: int ny = ANativeWindow_getHeight(app->window); nuclear@0: if(nx != win_width || ny != win_height) { nuclear@0: app_resize(nx, ny); nuclear@0: win_width = nx; nuclear@0: win_height = ny; nuclear@0: } nuclear@0: } nuclear@0: break; nuclear@0: nuclear@0: default: nuclear@0: break; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: static int handle_input(struct android_app *app, AInputEvent *ev) nuclear@0: { nuclear@0: int evtype = AInputEvent_getType(ev); nuclear@0: nuclear@0: switch(evtype) { nuclear@0: case AINPUT_EVENT_TYPE_MOTION: nuclear@0: return handle_touch_input(app, ev); nuclear@0: nuclear@0: default: nuclear@0: break; nuclear@0: } nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: #define MAX_TOUCH_IDS 32 nuclear@0: nuclear@0: static int handle_touch_input(struct android_app *app, AInputEvent *ev) nuclear@0: { nuclear@0: int x, y, idx, touch_id; nuclear@0: unsigned int action; nuclear@0: static int prev_pos[MAX_TOUCH_IDS][2]; nuclear@0: nuclear@0: action = AMotionEvent_getAction(ev); nuclear@0: nuclear@0: idx = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> nuclear@0: AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; nuclear@0: touch_id = AMotionEvent_getPointerId(ev, idx); nuclear@0: nuclear@0: x = AMotionEvent_getX(ev, idx); nuclear@0: y = AMotionEvent_getY(ev, idx); nuclear@0: nuclear@0: switch(action & AMOTION_EVENT_ACTION_MASK) { nuclear@0: case AMOTION_EVENT_ACTION_DOWN: nuclear@0: case AMOTION_EVENT_ACTION_POINTER_DOWN: nuclear@0: app_touch(touch_id, 1, x, y); nuclear@0: if(touch_id < MAX_TOUCH_IDS) { nuclear@0: prev_pos[touch_id][0] = x; nuclear@0: prev_pos[touch_id][1] = y; nuclear@0: } nuclear@0: break; nuclear@0: nuclear@0: case AMOTION_EVENT_ACTION_UP: nuclear@0: case AMOTION_EVENT_ACTION_POINTER_UP: nuclear@0: app_touch(touch_id, 0, x, y); nuclear@0: if(touch_id < MAX_TOUCH_IDS) { nuclear@0: prev_pos[touch_id][0] = x; nuclear@0: prev_pos[touch_id][1] = y; nuclear@0: } nuclear@0: break; nuclear@0: nuclear@0: case AMOTION_EVENT_ACTION_MOVE: nuclear@0: { nuclear@0: int i, pcount = AMotionEvent_getPointerCount(ev); nuclear@0: for(i=0; iwindow, 0, 0, vis); nuclear@0: nuclear@0: if(!(surf = eglCreateWindowSurface(dpy, eglcfg, app->window, 0))) { nuclear@0: fprintf(stderr, "failed to create window\n"); nuclear@0: destroy_gl(); nuclear@0: return -1; nuclear@0: } nuclear@0: nuclear@0: if(!(ctx = eglCreateContext(dpy, eglcfg, EGL_NO_CONTEXT, ctxattr))) { nuclear@0: fprintf(stderr, "failed to create OpenGL ES context\n"); nuclear@0: destroy_gl(); nuclear@0: return -1; nuclear@0: } nuclear@0: eglMakeCurrent(dpy, surf, surf, ctx); nuclear@0: nuclear@0: eglQuerySurface(dpy, surf, EGL_WIDTH, &win_width); nuclear@0: eglQuerySurface(dpy, surf, EGL_HEIGHT, &win_height); nuclear@0: app_resize(win_width, win_height); nuclear@0: nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: static void destroy_gl(void) nuclear@0: { nuclear@0: if(!dpy) return; nuclear@0: nuclear@0: eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); nuclear@0: nuclear@0: if(ctx) { nuclear@0: eglDestroyContext(dpy, ctx); nuclear@0: ctx = 0; nuclear@0: } nuclear@0: if(surf) { nuclear@0: eglDestroySurface(dpy, surf); nuclear@0: surf = 0; nuclear@0: } nuclear@0: nuclear@0: eglTerminate(dpy); nuclear@0: dpy = 0; nuclear@0: } nuclear@0: