labyrinth

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