labyrinth
diff 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 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/android/amain.c Fri May 01 04:36:50 2015 +0300 1.3 @@ -0,0 +1,251 @@ 1.4 +#include <stdio.h> 1.5 +#include <stdlib.h> 1.6 +#include <EGL/egl.h> 1.7 +#include <android_native_app_glue.h> 1.8 +#include "logger.h" 1.9 +#include "game.h" 1.10 +#include "timer.h" 1.11 + 1.12 + 1.13 +static void handle_command(struct android_app *app, int32_t cmd); 1.14 +static int handle_input(struct android_app *app, AInputEvent *ev); 1.15 +static int handle_touch_input(struct android_app *app, AInputEvent *ev); 1.16 +static int init_gl(void); 1.17 +static void destroy_gl(void); 1.18 + 1.19 +static EGLDisplay dpy; 1.20 +static EGLSurface surf; 1.21 +static EGLContext ctx; 1.22 + 1.23 +static struct android_app *app; 1.24 +static int win_width, win_height; 1.25 + 1.26 +void android_main(struct android_app *app_ptr) 1.27 +{ 1.28 + app_dummy(); 1.29 + app = app_ptr; 1.30 + 1.31 + app->onAppCmd = handle_command; 1.32 + app->onInputEvent = handle_input; 1.33 + 1.34 + start_logger(); 1.35 + 1.36 + for(;;) { 1.37 + int num_events; 1.38 + struct android_poll_source *pollsrc; 1.39 + 1.40 + while(ALooper_pollAll(0, 0, &num_events, (void**)&pollsrc) >= 0) { 1.41 + if(pollsrc) { 1.42 + pollsrc->process(app, pollsrc); 1.43 + } 1.44 + } 1.45 + 1.46 + if(app->destroyRequested) { 1.47 + return; 1.48 + } 1.49 + 1.50 + game_display(get_time_msec()); 1.51 + } 1.52 +} 1.53 + 1.54 +void set_mouse_pos(int x, int y) 1.55 +{ 1.56 +} 1.57 + 1.58 +void set_mouse_cursor(int enable) 1.59 +{ 1.60 +} 1.61 + 1.62 +static void handle_command(struct android_app *app, int32_t cmd) 1.63 +{ 1.64 + switch(cmd) { 1.65 + case APP_CMD_SAVE_STATE: 1.66 + /* save the application state to be reloaded on restart if needed */ 1.67 + break; 1.68 + 1.69 + case APP_CMD_INIT_WINDOW: 1.70 + if(init_gl() == -1) { 1.71 + exit(1); 1.72 + } 1.73 + /* initialize the application */ 1.74 + if(game_init() == -1) { 1.75 + exit(1); /* initialization failed, quit */ 1.76 + } 1.77 + break; 1.78 + 1.79 + case APP_CMD_TERM_WINDOW: 1.80 + /* cleanup */ 1.81 + game_shutdown(); 1.82 + destroy_gl(); 1.83 + break; 1.84 + 1.85 + case APP_CMD_GAINED_FOCUS: 1.86 + /* app focused */ 1.87 + break; 1.88 + 1.89 + case APP_CMD_LOST_FOCUS: 1.90 + /* app lost focus */ 1.91 + break; 1.92 + 1.93 + case APP_CMD_WINDOW_RESIZED: 1.94 + case APP_CMD_CONFIG_CHANGED: 1.95 + { 1.96 + int nx = ANativeWindow_getWidth(app->window); 1.97 + int ny = ANativeWindow_getHeight(app->window); 1.98 + if(nx != win_width || ny != win_height) { 1.99 + game_reshape(nx, ny); 1.100 + win_width = nx; 1.101 + win_height = ny; 1.102 + } 1.103 + } 1.104 + break; 1.105 + 1.106 + default: 1.107 + break; 1.108 + } 1.109 +} 1.110 + 1.111 +static int handle_input(struct android_app *app, AInputEvent *ev) 1.112 +{ 1.113 + int evtype = AInputEvent_getType(ev); 1.114 + 1.115 + switch(evtype) { 1.116 + case AINPUT_EVENT_TYPE_MOTION: 1.117 + return handle_touch_input(app, ev); 1.118 + 1.119 + default: 1.120 + break; 1.121 + } 1.122 + return 0; 1.123 +} 1.124 + 1.125 +#define MAX_TOUCH_IDS 32 1.126 + 1.127 +static int handle_touch_input(struct android_app *app, AInputEvent *ev) 1.128 +{ 1.129 + int x, y, idx, touch_id; 1.130 + unsigned int action; 1.131 + static int prev_pos[MAX_TOUCH_IDS][2]; 1.132 + 1.133 + action = AMotionEvent_getAction(ev); 1.134 + 1.135 + idx = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> 1.136 + AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; 1.137 + touch_id = AMotionEvent_getPointerId(ev, idx); 1.138 + 1.139 + x = AMotionEvent_getX(ev, idx); 1.140 + y = AMotionEvent_getY(ev, idx); 1.141 + 1.142 + switch(action & AMOTION_EVENT_ACTION_MASK) { 1.143 + case AMOTION_EVENT_ACTION_DOWN: 1.144 + case AMOTION_EVENT_ACTION_POINTER_DOWN: 1.145 + game_mouse_button(touch_id, 0, 1, x, y); 1.146 + if(touch_id < MAX_TOUCH_IDS) { 1.147 + prev_pos[touch_id][0] = x; 1.148 + prev_pos[touch_id][1] = y; 1.149 + } 1.150 + break; 1.151 + 1.152 + case AMOTION_EVENT_ACTION_UP: 1.153 + case AMOTION_EVENT_ACTION_POINTER_UP: 1.154 + game_mouse_button(touch_id, 0, 0, x, y); 1.155 + if(touch_id < MAX_TOUCH_IDS) { 1.156 + prev_pos[touch_id][0] = x; 1.157 + prev_pos[touch_id][1] = y; 1.158 + } 1.159 + break; 1.160 + 1.161 + case AMOTION_EVENT_ACTION_MOVE: 1.162 + { 1.163 + int i, pcount = AMotionEvent_getPointerCount(ev); 1.164 + for(i=0; i<pcount; i++) { 1.165 + int id = AMotionEvent_getPointerId(ev, i); 1.166 + if(id < MAX_TOUCH_IDS && x != prev_pos[id][0] && y != prev_pos[id][1]) { 1.167 + game_mouse_motion(id, x, y); 1.168 + prev_pos[id][0] = x; 1.169 + prev_pos[id][1] = y; 1.170 + } 1.171 + } 1.172 + } 1.173 + break; 1.174 + 1.175 + default: 1.176 + break; 1.177 + } 1.178 + 1.179 + return 1; 1.180 +} 1.181 + 1.182 + 1.183 +static int init_gl(void) 1.184 +{ 1.185 + static const int eglattr[] = { 1.186 + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 1.187 + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, 1.188 + EGL_RED_SIZE, 5, 1.189 + EGL_GREEN_SIZE, 5, 1.190 + EGL_BLUE_SIZE, 5, 1.191 + EGL_DEPTH_SIZE, 16, 1.192 + EGL_NONE 1.193 + }; 1.194 + static const int ctxattr[] = { EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE }; 1.195 + 1.196 + EGLConfig eglcfg; 1.197 + int count, vis; 1.198 + 1.199 + dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); 1.200 + if(!dpy || !eglInitialize(dpy, 0, 0)) { 1.201 + fprintf(stderr, "failed to initialize EGL\n"); 1.202 + destroy_gl(); 1.203 + return -1; 1.204 + } 1.205 + 1.206 + if(!eglChooseConfig(dpy, eglattr, &eglcfg, 1, &count)) { 1.207 + fprintf(stderr, "no matching EGL config found\n"); 1.208 + destroy_gl(); 1.209 + return -1; 1.210 + } 1.211 + 1.212 + /* configure the native window visual according to the chosen EGL config */ 1.213 + eglGetConfigAttrib(dpy, &eglcfg, EGL_NATIVE_VISUAL_ID, &vis); 1.214 + ANativeWindow_setBuffersGeometry(app->window, 0, 0, vis); 1.215 + 1.216 + if(!(surf = eglCreateWindowSurface(dpy, eglcfg, app->window, 0))) { 1.217 + fprintf(stderr, "failed to create window\n"); 1.218 + destroy_gl(); 1.219 + return -1; 1.220 + } 1.221 + 1.222 + if(!(ctx = eglCreateContext(dpy, eglcfg, EGL_NO_CONTEXT, ctxattr))) { 1.223 + fprintf(stderr, "failed to create OpenGL ES context\n"); 1.224 + destroy_gl(); 1.225 + return -1; 1.226 + } 1.227 + eglMakeCurrent(dpy, surf, surf, ctx); 1.228 + 1.229 + eglQuerySurface(dpy, surf, EGL_WIDTH, &win_width); 1.230 + eglQuerySurface(dpy, surf, EGL_HEIGHT, &win_height); 1.231 + game_reshape(win_width, win_height); 1.232 + 1.233 + return 0; 1.234 +} 1.235 + 1.236 +static void destroy_gl(void) 1.237 +{ 1.238 + if(!dpy) return; 1.239 + 1.240 + eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 1.241 + 1.242 + if(ctx) { 1.243 + eglDestroyContext(dpy, ctx); 1.244 + ctx = 0; 1.245 + } 1.246 + if(surf) { 1.247 + eglDestroySurface(dpy, surf); 1.248 + surf = 0; 1.249 + } 1.250 + 1.251 + eglTerminate(dpy); 1.252 + dpy = 0; 1.253 +} 1.254 +