istereo2

view src/android/amain.c @ 24:9d53a4938ce8

port to android mostly complete, ads not done, and needs some polishing
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 04 Oct 2015 08:15:24 +0300
parents 7d795dade0bc
children f0da8b2b61ec
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <EGL/egl.h>
5 #include "android_native_app_glue.h"
6 #include <android/window.h>
7 #include <android/sensor.h>
8 #include "logger.h"
9 #include "istereo.h"
11 struct android_app *app;
13 static void handle_command(struct android_app *app, int32_t cmd);
14 static int handle_input(struct android_app *app, AInputEvent *ev);
15 static int handle_touch_input(struct android_app *app, AInputEvent *ev);
16 static int init_gl(void);
17 static void destroy_gl(void);
19 static EGLDisplay dpy;
20 static EGLSurface surf;
21 static EGLContext ctx;
23 static int redisp_pending = 1; /* TODO stop busy-looping */
25 static int width, height;
26 static int init_done;
28 void android_main(struct android_app *app_ptr)
29 {
30 app_dummy();
31 app = app_ptr;
33 app->onAppCmd = handle_command;
34 app->onInputEvent = handle_input;
36 //ANativeActivity_setWindowFlags(app->activity, AWINDOW_FLAG_FULLSCREEN, 0);
38 start_logger();
40 for(;;) {
41 int num_events;
42 struct android_poll_source *pollsrc;
44 while(ALooper_pollAll(0, 0, &num_events, (void**)&pollsrc) >= 0) {
45 if(pollsrc) {
46 pollsrc->process(app, pollsrc);
47 }
48 }
50 if(app->destroyRequested) {
51 return;
52 }
54 if(init_done && redisp_pending) {
55 redraw();
56 eglSwapBuffers(dpy, surf);
57 }
58 }
59 }
61 void set_mouse_pos(int x, int y)
62 {
63 }
65 void set_mouse_cursor(int enable)
66 {
67 }
69 /* TODO */
70 void ad_banner_show(void)
71 {
72 }
74 void ad_banner_hide(void)
75 {
76 }
78 static void handle_command(struct android_app *app, int32_t cmd)
79 {
80 switch(cmd) {
81 case APP_CMD_SAVE_STATE:
82 /* save the application state to be reloaded on restart if needed */
83 break;
85 case APP_CMD_INIT_WINDOW:
86 printf("APP_CMD_INIT_WINDOW\n");
87 if(init_gl() == -1) {
88 exit(1);
89 }
90 /* initialize the application */
91 if(init() == -1) {
92 exit(1); /* initialization failed, quit */
93 }
94 reshape(width, height);
95 init_done = 1;
96 break;
98 case APP_CMD_TERM_WINDOW:
99 /* cleanup */
100 printf("APP_CMD_TERM_WINDOW\n");
101 init_done = 0;
102 cleanup();
103 destroy_gl();
104 break;
106 case APP_CMD_GAINED_FOCUS:
107 printf("APP_CMD_GAINED_FOCUS\n");
108 /* app focused */
109 break;
111 case APP_CMD_LOST_FOCUS:
112 printf("APP_CMD_LOST_FOCUS\n");
113 /* app lost focus */
114 break;
116 case APP_CMD_WINDOW_RESIZED:
117 case APP_CMD_CONFIG_CHANGED:
118 {
119 int nx = ANativeWindow_getWidth(app->window);
120 int ny = ANativeWindow_getHeight(app->window);
121 if(nx != width || ny != height) {
122 printf("reshape(%d, %d)\n", nx, ny);
123 reshape(nx, ny);
124 width = nx;
125 height = ny;
126 }
127 }
128 break;
130 default:
131 break;
132 }
133 }
135 static int handle_input(struct android_app *app, AInputEvent *ev)
136 {
137 int evtype = AInputEvent_getType(ev);
139 switch(evtype) {
140 case AINPUT_EVENT_TYPE_MOTION:
141 return handle_touch_input(app, ev);
143 default:
144 break;
145 }
146 return 0;
147 }
149 #define MAX_TOUCH_IDS 32
151 static int handle_touch_input(struct android_app *app, AInputEvent *ev)
152 {
153 int x, y, idx, touch_id;
154 unsigned int action;
155 static int prev_pos[MAX_TOUCH_IDS][2];
157 action = AMotionEvent_getAction(ev);
159 idx = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >>
160 AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
161 touch_id = AMotionEvent_getPointerId(ev, idx);
163 x = AMotionEvent_getX(ev, idx);
164 y = AMotionEvent_getY(ev, idx);
166 switch(action & AMOTION_EVENT_ACTION_MASK) {
167 case AMOTION_EVENT_ACTION_DOWN:
168 case AMOTION_EVENT_ACTION_POINTER_DOWN:
169 if(touch_id == 0) {
170 mouse_button(0, 1, x, y);
171 }
172 if(touch_id < MAX_TOUCH_IDS) {
173 prev_pos[touch_id][0] = x;
174 prev_pos[touch_id][1] = y;
175 }
176 break;
178 case AMOTION_EVENT_ACTION_UP:
179 case AMOTION_EVENT_ACTION_POINTER_UP:
180 if(touch_id == 0) {
181 mouse_button(0, 0, x, y);
182 }
183 if(touch_id < MAX_TOUCH_IDS) {
184 prev_pos[touch_id][0] = x;
185 prev_pos[touch_id][1] = y;
186 }
187 break;
189 case AMOTION_EVENT_ACTION_MOVE:
190 {
191 int i, pcount = AMotionEvent_getPointerCount(ev);
192 for(i=0; i<pcount; i++) {
193 int id = AMotionEvent_getPointerId(ev, i);
194 if(id < MAX_TOUCH_IDS && x != prev_pos[id][0] && y != prev_pos[id][1]) {
195 if(id == 0) {
196 mouse_motion(x, y);
197 }
198 prev_pos[id][0] = x;
199 prev_pos[id][1] = y;
200 }
201 }
202 }
203 break;
205 default:
206 break;
207 }
209 return 1;
210 }
213 static int init_gl(void)
214 {
215 static const int eglattr[] = {
216 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
217 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
218 EGL_RED_SIZE, 5,
219 EGL_GREEN_SIZE, 5,
220 EGL_BLUE_SIZE, 5,
221 EGL_DEPTH_SIZE, 16,
222 EGL_NONE
223 };
224 static const int ctxattr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
226 EGLConfig eglcfg;
227 int count, vis;
229 dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
230 if(!dpy || !eglInitialize(dpy, 0, 0)) {
231 fprintf(stderr, "failed to initialize EGL\n");
232 destroy_gl();
233 return -1;
234 }
236 if(!eglChooseConfig(dpy, eglattr, &eglcfg, 1, &count)) {
237 fprintf(stderr, "no matching EGL config found\n");
238 destroy_gl();
239 return -1;
240 }
242 /* configure the native window visual according to the chosen EGL config */
243 eglGetConfigAttrib(dpy, &eglcfg, EGL_NATIVE_VISUAL_ID, &vis);
244 ANativeWindow_setBuffersGeometry(app->window, 0, 0, vis);
246 if(!(surf = eglCreateWindowSurface(dpy, eglcfg, app->window, 0))) {
247 fprintf(stderr, "failed to create window\n");
248 destroy_gl();
249 return -1;
250 }
252 if(!(ctx = eglCreateContext(dpy, eglcfg, EGL_NO_CONTEXT, ctxattr))) {
253 fprintf(stderr, "failed to create OpenGL ES context\n");
254 destroy_gl();
255 return -1;
256 }
257 eglMakeCurrent(dpy, surf, surf, ctx);
259 eglQuerySurface(dpy, surf, EGL_WIDTH, &width);
260 eglQuerySurface(dpy, surf, EGL_HEIGHT, &height);
261 printf("initial reshape call: %dx%d\n", width, height);
262 reshape(width, height);
264 return 0;
265 }
267 static void destroy_gl(void)
268 {
269 if(!dpy) return;
271 eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
273 if(ctx) {
274 eglDestroyContext(dpy, ctx);
275 ctx = 0;
276 }
277 if(surf) {
278 eglDestroySurface(dpy, surf);
279 surf = 0;
280 }
282 eglTerminate(dpy);
283 dpy = 0;
284 }