labyrinth

annotate src/android/amain.c @ 3:45b91185b298

android port
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 01 May 2015 04:36:50 +0300
parents
children d3f1f74067b0
rev   line source
nuclear@3 1 #include <stdio.h>
nuclear@3 2 #include <stdlib.h>
nuclear@3 3 #include <EGL/egl.h>
nuclear@3 4 #include <android_native_app_glue.h>
nuclear@3 5 #include "logger.h"
nuclear@3 6 #include "game.h"
nuclear@3 7 #include "timer.h"
nuclear@3 8
nuclear@3 9
nuclear@3 10 static void handle_command(struct android_app *app, int32_t cmd);
nuclear@3 11 static int handle_input(struct android_app *app, AInputEvent *ev);
nuclear@3 12 static int handle_touch_input(struct android_app *app, AInputEvent *ev);
nuclear@3 13 static int init_gl(void);
nuclear@3 14 static void destroy_gl(void);
nuclear@3 15
nuclear@3 16 static EGLDisplay dpy;
nuclear@3 17 static EGLSurface surf;
nuclear@3 18 static EGLContext ctx;
nuclear@3 19
nuclear@3 20 static struct android_app *app;
nuclear@3 21 static int win_width, win_height;
nuclear@3 22
nuclear@3 23 void android_main(struct android_app *app_ptr)
nuclear@3 24 {
nuclear@3 25 app_dummy();
nuclear@3 26 app = app_ptr;
nuclear@3 27
nuclear@3 28 app->onAppCmd = handle_command;
nuclear@3 29 app->onInputEvent = handle_input;
nuclear@3 30
nuclear@3 31 start_logger();
nuclear@3 32
nuclear@3 33 for(;;) {
nuclear@3 34 int num_events;
nuclear@3 35 struct android_poll_source *pollsrc;
nuclear@3 36
nuclear@3 37 while(ALooper_pollAll(0, 0, &num_events, (void**)&pollsrc) >= 0) {
nuclear@3 38 if(pollsrc) {
nuclear@3 39 pollsrc->process(app, pollsrc);
nuclear@3 40 }
nuclear@3 41 }
nuclear@3 42
nuclear@3 43 if(app->destroyRequested) {
nuclear@3 44 return;
nuclear@3 45 }
nuclear@3 46
nuclear@3 47 game_display(get_time_msec());
nuclear@3 48 }
nuclear@3 49 }
nuclear@3 50
nuclear@3 51 void set_mouse_pos(int x, int y)
nuclear@3 52 {
nuclear@3 53 }
nuclear@3 54
nuclear@3 55 void set_mouse_cursor(int enable)
nuclear@3 56 {
nuclear@3 57 }
nuclear@3 58
nuclear@3 59 static void handle_command(struct android_app *app, int32_t cmd)
nuclear@3 60 {
nuclear@3 61 switch(cmd) {
nuclear@3 62 case APP_CMD_SAVE_STATE:
nuclear@3 63 /* save the application state to be reloaded on restart if needed */
nuclear@3 64 break;
nuclear@3 65
nuclear@3 66 case APP_CMD_INIT_WINDOW:
nuclear@3 67 if(init_gl() == -1) {
nuclear@3 68 exit(1);
nuclear@3 69 }
nuclear@3 70 /* initialize the application */
nuclear@3 71 if(game_init() == -1) {
nuclear@3 72 exit(1); /* initialization failed, quit */
nuclear@3 73 }
nuclear@3 74 break;
nuclear@3 75
nuclear@3 76 case APP_CMD_TERM_WINDOW:
nuclear@3 77 /* cleanup */
nuclear@3 78 game_shutdown();
nuclear@3 79 destroy_gl();
nuclear@3 80 break;
nuclear@3 81
nuclear@3 82 case APP_CMD_GAINED_FOCUS:
nuclear@3 83 /* app focused */
nuclear@3 84 break;
nuclear@3 85
nuclear@3 86 case APP_CMD_LOST_FOCUS:
nuclear@3 87 /* app lost focus */
nuclear@3 88 break;
nuclear@3 89
nuclear@3 90 case APP_CMD_WINDOW_RESIZED:
nuclear@3 91 case APP_CMD_CONFIG_CHANGED:
nuclear@3 92 {
nuclear@3 93 int nx = ANativeWindow_getWidth(app->window);
nuclear@3 94 int ny = ANativeWindow_getHeight(app->window);
nuclear@3 95 if(nx != win_width || ny != win_height) {
nuclear@3 96 game_reshape(nx, ny);
nuclear@3 97 win_width = nx;
nuclear@3 98 win_height = ny;
nuclear@3 99 }
nuclear@3 100 }
nuclear@3 101 break;
nuclear@3 102
nuclear@3 103 default:
nuclear@3 104 break;
nuclear@3 105 }
nuclear@3 106 }
nuclear@3 107
nuclear@3 108 static int handle_input(struct android_app *app, AInputEvent *ev)
nuclear@3 109 {
nuclear@3 110 int evtype = AInputEvent_getType(ev);
nuclear@3 111
nuclear@3 112 switch(evtype) {
nuclear@3 113 case AINPUT_EVENT_TYPE_MOTION:
nuclear@3 114 return handle_touch_input(app, ev);
nuclear@3 115
nuclear@3 116 default:
nuclear@3 117 break;
nuclear@3 118 }
nuclear@3 119 return 0;
nuclear@3 120 }
nuclear@3 121
nuclear@3 122 #define MAX_TOUCH_IDS 32
nuclear@3 123
nuclear@3 124 static int handle_touch_input(struct android_app *app, AInputEvent *ev)
nuclear@3 125 {
nuclear@3 126 int x, y, idx, touch_id;
nuclear@3 127 unsigned int action;
nuclear@3 128 static int prev_pos[MAX_TOUCH_IDS][2];
nuclear@3 129
nuclear@3 130 action = AMotionEvent_getAction(ev);
nuclear@3 131
nuclear@3 132 idx = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >>
nuclear@3 133 AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
nuclear@3 134 touch_id = AMotionEvent_getPointerId(ev, idx);
nuclear@3 135
nuclear@3 136 x = AMotionEvent_getX(ev, idx);
nuclear@3 137 y = AMotionEvent_getY(ev, idx);
nuclear@3 138
nuclear@3 139 switch(action & AMOTION_EVENT_ACTION_MASK) {
nuclear@3 140 case AMOTION_EVENT_ACTION_DOWN:
nuclear@3 141 case AMOTION_EVENT_ACTION_POINTER_DOWN:
nuclear@3 142 game_mouse_button(touch_id, 0, 1, x, y);
nuclear@3 143 if(touch_id < MAX_TOUCH_IDS) {
nuclear@3 144 prev_pos[touch_id][0] = x;
nuclear@3 145 prev_pos[touch_id][1] = y;
nuclear@3 146 }
nuclear@3 147 break;
nuclear@3 148
nuclear@3 149 case AMOTION_EVENT_ACTION_UP:
nuclear@3 150 case AMOTION_EVENT_ACTION_POINTER_UP:
nuclear@3 151 game_mouse_button(touch_id, 0, 0, x, y);
nuclear@3 152 if(touch_id < MAX_TOUCH_IDS) {
nuclear@3 153 prev_pos[touch_id][0] = x;
nuclear@3 154 prev_pos[touch_id][1] = y;
nuclear@3 155 }
nuclear@3 156 break;
nuclear@3 157
nuclear@3 158 case AMOTION_EVENT_ACTION_MOVE:
nuclear@3 159 {
nuclear@3 160 int i, pcount = AMotionEvent_getPointerCount(ev);
nuclear@3 161 for(i=0; i<pcount; i++) {
nuclear@3 162 int id = AMotionEvent_getPointerId(ev, i);
nuclear@3 163 if(id < MAX_TOUCH_IDS && x != prev_pos[id][0] && y != prev_pos[id][1]) {
nuclear@3 164 game_mouse_motion(id, x, y);
nuclear@3 165 prev_pos[id][0] = x;
nuclear@3 166 prev_pos[id][1] = y;
nuclear@3 167 }
nuclear@3 168 }
nuclear@3 169 }
nuclear@3 170 break;
nuclear@3 171
nuclear@3 172 default:
nuclear@3 173 break;
nuclear@3 174 }
nuclear@3 175
nuclear@3 176 return 1;
nuclear@3 177 }
nuclear@3 178
nuclear@3 179
nuclear@3 180 static int init_gl(void)
nuclear@3 181 {
nuclear@3 182 static const int eglattr[] = {
nuclear@3 183 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
nuclear@3 184 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
nuclear@3 185 EGL_RED_SIZE, 5,
nuclear@3 186 EGL_GREEN_SIZE, 5,
nuclear@3 187 EGL_BLUE_SIZE, 5,
nuclear@3 188 EGL_DEPTH_SIZE, 16,
nuclear@3 189 EGL_NONE
nuclear@3 190 };
nuclear@3 191 static const int ctxattr[] = { EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE };
nuclear@3 192
nuclear@3 193 EGLConfig eglcfg;
nuclear@3 194 int count, vis;
nuclear@3 195
nuclear@3 196 dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
nuclear@3 197 if(!dpy || !eglInitialize(dpy, 0, 0)) {
nuclear@3 198 fprintf(stderr, "failed to initialize EGL\n");
nuclear@3 199 destroy_gl();
nuclear@3 200 return -1;
nuclear@3 201 }
nuclear@3 202
nuclear@3 203 if(!eglChooseConfig(dpy, eglattr, &eglcfg, 1, &count)) {
nuclear@3 204 fprintf(stderr, "no matching EGL config found\n");
nuclear@3 205 destroy_gl();
nuclear@3 206 return -1;
nuclear@3 207 }
nuclear@3 208
nuclear@3 209 /* configure the native window visual according to the chosen EGL config */
nuclear@3 210 eglGetConfigAttrib(dpy, &eglcfg, EGL_NATIVE_VISUAL_ID, &vis);
nuclear@3 211 ANativeWindow_setBuffersGeometry(app->window, 0, 0, vis);
nuclear@3 212
nuclear@3 213 if(!(surf = eglCreateWindowSurface(dpy, eglcfg, app->window, 0))) {
nuclear@3 214 fprintf(stderr, "failed to create window\n");
nuclear@3 215 destroy_gl();
nuclear@3 216 return -1;
nuclear@3 217 }
nuclear@3 218
nuclear@3 219 if(!(ctx = eglCreateContext(dpy, eglcfg, EGL_NO_CONTEXT, ctxattr))) {
nuclear@3 220 fprintf(stderr, "failed to create OpenGL ES context\n");
nuclear@3 221 destroy_gl();
nuclear@3 222 return -1;
nuclear@3 223 }
nuclear@3 224 eglMakeCurrent(dpy, surf, surf, ctx);
nuclear@3 225
nuclear@3 226 eglQuerySurface(dpy, surf, EGL_WIDTH, &win_width);
nuclear@3 227 eglQuerySurface(dpy, surf, EGL_HEIGHT, &win_height);
nuclear@3 228 game_reshape(win_width, win_height);
nuclear@3 229
nuclear@3 230 return 0;
nuclear@3 231 }
nuclear@3 232
nuclear@3 233 static void destroy_gl(void)
nuclear@3 234 {
nuclear@3 235 if(!dpy) return;
nuclear@3 236
nuclear@3 237 eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
nuclear@3 238
nuclear@3 239 if(ctx) {
nuclear@3 240 eglDestroyContext(dpy, ctx);
nuclear@3 241 ctx = 0;
nuclear@3 242 }
nuclear@3 243 if(surf) {
nuclear@3 244 eglDestroySurface(dpy, surf);
nuclear@3 245 surf = 0;
nuclear@3 246 }
nuclear@3 247
nuclear@3 248 eglTerminate(dpy);
nuclear@3 249 dpy = 0;
nuclear@3 250 }
nuclear@3 251