labyrinth

annotate src/android/amain.c @ 8:d3f1f74067b0

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