ndktest

view 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 source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <GLES/gl.h>
5 #include <GLES/glext.h>
6 #include <EGL/egl.h>
7 #include <android_native_app_glue.h>
8 #include "app.h"
9 #include "logger.h"
11 static void handle_command(struct android_app *app, int32_t cmd);
12 static int handle_input(struct android_app *app, AInputEvent *ev);
13 static int handle_touch_input(struct android_app *app, AInputEvent *ev);
14 static int init_gl(void);
15 static void destroy_gl(void);
17 static struct android_app *app;
18 static int win_width, win_height;
20 void android_main(struct android_app *app_ptr)
21 {
22 app_dummy();
23 app = app_ptr;
25 app->onAppCmd = handle_command;
26 app->onInputEvent = handle_input;
28 start_logger();
30 for(;;) {
31 int num_events;
32 struct android_poll_source *pollsrc;
34 while(ALooper_pollAll(0, 0, &num_events, (void**)&pollsrc) >= 0) {
35 if(pollsrc) {
36 pollsrc->process(app, pollsrc);
37 }
38 }
40 if(app->destroyRequested) {
41 return;
42 }
44 app_display();
45 }
46 }
48 static void handle_command(struct android_app *app, int32_t cmd)
49 {
50 switch(cmd) {
51 case APP_CMD_SAVE_STATE:
52 /* save the application state to be reloaded on restart if needed */
53 break;
55 case APP_CMD_INIT_WINDOW:
56 if(init_gl() == -1) {
57 exit(1);
58 }
59 /* initialize the application */
60 if(app_init() == -1) {
61 exit(1); /* initialization failed, quit */
62 }
63 break;
65 case APP_CMD_TERM_WINDOW:
66 /* cleanup */
67 app_cleanup();
68 destroy_gl();
69 break;
71 case APP_CMD_GAINED_FOCUS:
72 /* app focused */
73 break;
75 case APP_CMD_LOST_FOCUS:
76 /* app lost focus */
77 break;
79 case APP_CMD_WINDOW_RESIZED:
80 case APP_CMD_CONFIG_CHANGED:
81 {
82 int nx = ANativeWindow_getWidth(app->window);
83 int ny = ANativeWindow_getHeight(app->window);
84 if(nx != win_width || ny != win_height) {
85 app_resize(nx, ny);
86 win_width = nx;
87 win_height = ny;
88 }
89 }
90 break;
92 default:
93 break;
94 }
95 }
97 static int handle_input(struct android_app *app, AInputEvent *ev)
98 {
99 int evtype = AInputEvent_getType(ev);
101 switch(evtype) {
102 case AINPUT_EVENT_TYPE_MOTION:
103 return handle_touch_input(app, ev);
105 default:
106 break;
107 }
108 return 0;
109 }
111 #define MAX_TOUCH_IDS 32
113 static int handle_touch_input(struct android_app *app, AInputEvent *ev)
114 {
115 int x, y, idx, touch_id;
116 unsigned int action;
117 static int prev_pos[MAX_TOUCH_IDS][2];
119 action = AMotionEvent_getAction(ev);
121 idx = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >>
122 AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
123 touch_id = AMotionEvent_getPointerId(ev, idx);
125 x = AMotionEvent_getX(ev, idx);
126 y = AMotionEvent_getY(ev, idx);
128 switch(action & AMOTION_EVENT_ACTION_MASK) {
129 case AMOTION_EVENT_ACTION_DOWN:
130 case AMOTION_EVENT_ACTION_POINTER_DOWN:
131 app_touch(touch_id, 1, x, y);
132 if(touch_id < MAX_TOUCH_IDS) {
133 prev_pos[touch_id][0] = x;
134 prev_pos[touch_id][1] = y;
135 }
136 break;
138 case AMOTION_EVENT_ACTION_UP:
139 case AMOTION_EVENT_ACTION_POINTER_UP:
140 app_touch(touch_id, 0, x, y);
141 if(touch_id < MAX_TOUCH_IDS) {
142 prev_pos[touch_id][0] = x;
143 prev_pos[touch_id][1] = y;
144 }
145 break;
147 case AMOTION_EVENT_ACTION_MOVE:
148 {
149 int i, pcount = AMotionEvent_getPointerCount(ev);
150 for(i=0; i<pcount; i++) {
151 int id = AMotionEvent_getPointerId(ev, i);
152 if(id < MAX_TOUCH_IDS && x != prev_pos[id][0] && y != prev_pos[id][1]) {
153 app_drag(id, x, y);
154 prev_pos[id][0] = x;
155 prev_pos[id][1] = y;
156 }
157 }
158 }
159 break;
161 default:
162 break;
163 }
165 return 1;
166 }
169 static int init_gl(void)
170 {
171 static const int eglattr[] = {
172 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
173 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
174 EGL_RED_SIZE, 5,
175 EGL_GREEN_SIZE, 5,
176 EGL_BLUE_SIZE, 5,
177 EGL_DEPTH_SIZE, 16,
178 EGL_NONE
179 };
180 static const int ctxattr[] = { EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE };
182 EGLConfig eglcfg;
183 int count, vis;
185 dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
186 if(!dpy || !eglInitialize(dpy, 0, 0)) {
187 fprintf(stderr, "failed to initialize EGL\n");
188 destroy_gl();
189 return -1;
190 }
192 if(!eglChooseConfig(dpy, eglattr, &eglcfg, 1, &count)) {
193 fprintf(stderr, "no matching EGL config found\n");
194 destroy_gl();
195 return -1;
196 }
198 /* configure the native window visual according to the chosen EGL config */
199 eglGetConfigAttrib(dpy, &eglcfg, EGL_NATIVE_VISUAL_ID, &vis);
200 ANativeWindow_setBuffersGeometry(app->window, 0, 0, vis);
202 if(!(surf = eglCreateWindowSurface(dpy, eglcfg, app->window, 0))) {
203 fprintf(stderr, "failed to create window\n");
204 destroy_gl();
205 return -1;
206 }
208 if(!(ctx = eglCreateContext(dpy, eglcfg, EGL_NO_CONTEXT, ctxattr))) {
209 fprintf(stderr, "failed to create OpenGL ES context\n");
210 destroy_gl();
211 return -1;
212 }
213 eglMakeCurrent(dpy, surf, surf, ctx);
215 eglQuerySurface(dpy, surf, EGL_WIDTH, &win_width);
216 eglQuerySurface(dpy, surf, EGL_HEIGHT, &win_height);
217 app_resize(win_width, win_height);
219 return 0;
220 }
222 static void destroy_gl(void)
223 {
224 if(!dpy) return;
226 eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
228 if(ctx) {
229 eglDestroyContext(dpy, ctx);
230 ctx = 0;
231 }
232 if(surf) {
233 eglDestroySurface(dpy, surf);
234 surf = 0;
235 }
237 eglTerminate(dpy);
238 dpy = 0;
239 }