istereo2

view src/android/amain.c @ 30:900651a2f401

foo
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 08 Oct 2015 06:54:18 +0300
parents c6c45fa9658d
children 48a0660bac82
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <EGL/egl.h>
5 #include <jni.h>
6 #include "android_native_app_glue.h"
7 #include <android/window.h>
8 #include <android/sensor.h>
9 #include "logger.h"
10 #include "istereo.h"
12 struct android_app *app;
14 static void handle_command(struct android_app *app, int32_t cmd);
15 static int handle_input(struct android_app *app, AInputEvent *ev);
16 static int handle_touch_input(struct android_app *app, AInputEvent *ev);
17 static int init_gl(void);
18 static void destroy_gl(void);
20 static EGLDisplay dpy;
21 static EGLSurface surf;
22 static EGLContext ctx;
24 static int redisp_pending = 1; /* TODO stop busy-looping */
26 static int width, height;
27 static int init_done;
29 static JavaVM *jvm;
30 static JNIEnv *jni;
31 static jclass activity_class;
32 static jobject activity;
34 void android_main(struct android_app *app_ptr)
35 {
36 app_dummy();
37 app = app_ptr;
39 app->onAppCmd = handle_command;
40 app->onInputEvent = handle_input;
42 //ANativeActivity_setWindowFlags(app->activity, AWINDOW_FLAG_FULLSCREEN, 0);
44 start_logger();
46 jvm = app->activity->vm;
47 if((*jvm)->AttachCurrentThread(jvm, &jni, 0) != 0) {
48 fprintf(stderr, "failed to attach native thread to Java VM\n");
49 exit(1);
50 }
51 activity = app->activity->clazz;
52 activity_class = (*jni)->GetObjectClass(jni, app->activity->clazz);
54 for(;;) {
55 int num_events;
56 struct android_poll_source *pollsrc;
58 while(ALooper_pollAll(0, 0, &num_events, (void**)&pollsrc) >= 0) {
59 if(pollsrc) {
60 pollsrc->process(app, pollsrc);
61 }
62 }
64 if(app->destroyRequested) {
65 return;
66 }
68 if(init_done && redisp_pending) {
69 redraw();
70 eglSwapBuffers(dpy, surf);
71 }
72 }
73 }
75 void set_mouse_pos(int x, int y)
76 {
77 }
79 void set_mouse_cursor(int enable)
80 {
81 }
83 void ad_banner_show(void)
84 {
85 jmethodID method;
86 if(!jvm) return;
88 if(!(method = (*jni)->GetMethodID(jni, activity_class, "show_ad", "()V"))) {
89 fprintf(stderr, "failed to retrieve MainActivity.show_ad method\n");
90 return;
91 }
92 (*jni)->CallVoidMethod(jni, activity, method);
93 }
95 void ad_banner_hide(void)
96 {
97 jmethodID method;
98 if(!jvm) return;
100 if(!(method = (*jni)->GetMethodID(jni, activity_class, "hide_ad", "()V"))) {
101 fprintf(stderr, "failed to retrieve MainActivity.hide_ad method\n");
102 return;
103 }
104 (*jni)->CallVoidMethod(jni, activity, method);
105 }
107 static void handle_command(struct android_app *app, int32_t cmd)
108 {
109 switch(cmd) {
110 case APP_CMD_SAVE_STATE:
111 /* save the application state to be reloaded on restart if needed */
112 break;
114 case APP_CMD_INIT_WINDOW:
115 printf("APP_CMD_INIT_WINDOW\n");
116 ad_banner_show();
118 if(init_gl() == -1) {
119 exit(1);
120 }
121 /* initialize the application */
122 if(init() == -1) {
123 exit(1); /* initialization failed, quit */
124 }
125 reshape(width, height);
126 init_done = 1;
127 break;
129 case APP_CMD_TERM_WINDOW:
130 /* cleanup */
131 printf("APP_CMD_TERM_WINDOW\n");
132 init_done = 0;
133 cleanup();
134 destroy_gl();
135 break;
137 case APP_CMD_GAINED_FOCUS:
138 printf("APP_CMD_GAINED_FOCUS\n");
139 /* app focused */
140 break;
142 case APP_CMD_LOST_FOCUS:
143 printf("APP_CMD_LOST_FOCUS\n");
144 /* app lost focus */
145 break;
147 case APP_CMD_WINDOW_RESIZED:
148 case APP_CMD_CONFIG_CHANGED:
149 {
150 int nx = ANativeWindow_getWidth(app->window);
151 int ny = ANativeWindow_getHeight(app->window);
152 if(nx != width || ny != height) {
153 printf("reshape(%d, %d)\n", nx, ny);
154 reshape(nx, ny);
155 width = nx;
156 height = ny;
157 }
158 }
159 break;
161 default:
162 break;
163 }
164 }
166 static int handle_input(struct android_app *app, AInputEvent *ev)
167 {
168 int evtype = AInputEvent_getType(ev);
170 switch(evtype) {
171 case AINPUT_EVENT_TYPE_MOTION:
172 return handle_touch_input(app, ev);
174 default:
175 break;
176 }
177 return 0;
178 }
180 #define MAX_TOUCH_IDS 32
182 static int handle_touch_input(struct android_app *app, AInputEvent *ev)
183 {
184 int x, y, idx, touch_id;
185 unsigned int action;
186 static int prev_pos[MAX_TOUCH_IDS][2];
188 action = AMotionEvent_getAction(ev);
190 idx = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >>
191 AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
192 touch_id = AMotionEvent_getPointerId(ev, idx);
194 x = AMotionEvent_getX(ev, idx);
195 y = AMotionEvent_getY(ev, idx);
197 switch(action & AMOTION_EVENT_ACTION_MASK) {
198 case AMOTION_EVENT_ACTION_DOWN:
199 case AMOTION_EVENT_ACTION_POINTER_DOWN:
200 if(touch_id == 0) {
201 mouse_button(0, 1, x, y);
202 }
203 if(touch_id < MAX_TOUCH_IDS) {
204 prev_pos[touch_id][0] = x;
205 prev_pos[touch_id][1] = y;
206 }
207 break;
209 case AMOTION_EVENT_ACTION_UP:
210 case AMOTION_EVENT_ACTION_POINTER_UP:
211 if(touch_id == 0) {
212 mouse_button(0, 0, x, y);
213 }
214 if(touch_id < MAX_TOUCH_IDS) {
215 prev_pos[touch_id][0] = x;
216 prev_pos[touch_id][1] = y;
217 }
218 break;
220 case AMOTION_EVENT_ACTION_MOVE:
221 {
222 int i, pcount = AMotionEvent_getPointerCount(ev);
223 for(i=0; i<pcount; i++) {
224 int id = AMotionEvent_getPointerId(ev, i);
225 if(id < MAX_TOUCH_IDS && x != prev_pos[id][0] && y != prev_pos[id][1]) {
226 if(id == 0) {
227 mouse_motion(x, y);
228 }
229 prev_pos[id][0] = x;
230 prev_pos[id][1] = y;
231 }
232 }
233 }
234 break;
236 default:
237 break;
238 }
240 return 1;
241 }
244 static int init_gl(void)
245 {
246 static const int eglattr[] = {
247 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
248 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
249 EGL_RED_SIZE, 5,
250 EGL_GREEN_SIZE, 5,
251 EGL_BLUE_SIZE, 5,
252 EGL_DEPTH_SIZE, 16,
253 EGL_NONE
254 };
255 static const int ctxattr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
257 EGLConfig eglcfg;
258 int count, vis;
260 dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
261 if(!dpy || !eglInitialize(dpy, 0, 0)) {
262 fprintf(stderr, "failed to initialize EGL\n");
263 destroy_gl();
264 return -1;
265 }
267 if(!eglChooseConfig(dpy, eglattr, &eglcfg, 1, &count)) {
268 fprintf(stderr, "no matching EGL config found\n");
269 destroy_gl();
270 return -1;
271 }
273 /* configure the native window visual according to the chosen EGL config */
274 eglGetConfigAttrib(dpy, &eglcfg, EGL_NATIVE_VISUAL_ID, &vis);
275 ANativeWindow_setBuffersGeometry(app->window, 0, 0, vis);
277 if(!(surf = eglCreateWindowSurface(dpy, eglcfg, app->window, 0))) {
278 fprintf(stderr, "failed to create window\n");
279 destroy_gl();
280 return -1;
281 }
283 if(!(ctx = eglCreateContext(dpy, eglcfg, EGL_NO_CONTEXT, ctxattr))) {
284 fprintf(stderr, "failed to create OpenGL ES context\n");
285 destroy_gl();
286 return -1;
287 }
288 eglMakeCurrent(dpy, surf, surf, ctx);
290 eglQuerySurface(dpy, surf, EGL_WIDTH, &width);
291 eglQuerySurface(dpy, surf, EGL_HEIGHT, &height);
292 printf("initial reshape call: %dx%d\n", width, height);
293 reshape(width, height);
295 return 0;
296 }
298 static void destroy_gl(void)
299 {
300 if(!dpy) return;
302 eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
304 if(ctx) {
305 eglDestroyContext(dpy, ctx);
306 ctx = 0;
307 }
308 if(surf) {
309 eglDestroySurface(dpy, surf);
310 surf = 0;
311 }
313 eglTerminate(dpy);
314 dpy = 0;
315 }