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