[size=1em]1 
[size=1em]2 
[size=1em]3 
[size=1em]4 
[size=1em]5 
[size=1em]6 
[size=1em]7 
[size=1em]8 
[size=1em]9 
[size=1em]10 
[size=1em]11 
[size=1em]12 
[size=1em]13 
[size=1em]14 
[size=1em]15 
[size=1em]16 
[size=1em]17 
[size=1em]18 
[size=1em]19 
[size=1em]20 
[size=1em]21 
[size=1em]22 
[size=1em]23 
[size=1em]24 
[size=1em]25 
[size=1em]26 
[size=1em]27 
[size=1em]28 
[size=1em]29 
[size=1em]30 
[size=1em]31 
[size=1em]32 
[size=1em]33 
[size=1em]34 
[size=1em]35 
[size=1em]36 
[size=1em]37 
[size=1em]38 
[size=1em]39 
[size=1em]40 
[size=1em]41 
[size=1em]42 
[size=1em]43 
[size=1em]44 
[size=1em]45 
[size=1em]46 
[size=1em]47 
[size=1em]48 
[size=1em]49 
[size=1em]50 
[size=1em]51 
[size=1em]52 
[size=1em]53 
[size=1em]54 
[size=1em]55 
[size=1em]56 
[size=1em]57 
[size=1em]58 
[size=1em]59 
[size=1em]60 
[size=1em]61 
[size=1em]62 
[size=1em]63 
[size=1em]64 
[size=1em]65 
[size=1em]66 
[size=1em]67 
[size=1em]68 
[size=1em]69 
[size=1em]70 
[size=1em]71 
[size=1em]72 
[size=1em]73 
[size=1em]74 
[size=1em]75 
[size=1em]76 
[size=1em]77 
[size=1em]78 
[size=1em]79 
[size=1em]80 
[size=1em]81 
[size=1em]82 
[size=1em]83 
[size=1em]84 
[size=1em]85 
[size=1em]86 
[size=1em]87 
[size=1em]88 
[size=1em]89 
[size=1em]90 
[size=1em]91 
[size=1em]92 
[size=1em]93 
[size=1em]94 
[size=1em]95 
[size=1em]96 
[size=1em]97 
[size=1em]98 
[size=1em]99 
[size=1em]100 
[size=1em]101 
[size=1em]102 
[size=1em]103 
[size=1em]104 
[size=1em]105 
[size=1em]106 
[size=1em]107 
[size=1em]108 
[size=1em]109 
[size=1em]110 
[size=1em]111 
[size=1em]112 
[size=1em]113 
[size=1em]114 
[size=1em]115 
[size=1em]116 
[size=1em]117 
[size=1em]118 
[size=1em]119 
[size=1em]120 
[size=1em]121 
[size=1em]122 
[size=1em]123 
[size=1em]124 
[size=1em]125 
[size=1em]126 
[size=1em]127 
[size=1em]128 
[size=1em]129 
[size=1em]130 
[size=1em]131 
[size=1em]132 
[size=1em]133 
[size=1em]134 
[size=1em]135 
[size=1em]136 
[size=1em]137 
[size=1em]138 
[size=1em]139 
[size=1em]140 
[size=1em]141 
[size=1em]142 
[size=1em]143 
[size=1em]144 
[size=1em]145 
[size=1em]146 
[size=1em]147 
[size=1em]148 
[size=1em]149 
[size=1em]150 
[size=1em]151 
[size=1em]152 
[size=1em]153 
[size=1em]154 
[size=1em]155 
[size=1em]156 
[size=1em]157 
[size=1em]158 
[size=1em]159 
[size=1em]160 
[size=1em]161 
[size=1em]162 
[size=1em]163 
[size=1em]164 
[size=1em]165 
[size=1em]166 
[size=1em]167 
[size=1em]168 
[size=1em]169 
[size=1em]170 
[size=1em]171 
[size=1em]172 
[size=1em]173 
[size=1em]174 
[size=1em]175 
[size=1em]176 
[size=1em]177 
[size=1em]178 
[size=1em]179 
[size=1em]180 
[size=1em]181 
[size=1em]182 
[size=1em]183 
[size=1em]184 
[size=1em]185 
[size=1em]186 
[size=1em]187 
[size=1em]188 
[size=1em]189 
[size=1em]190 
[size=1em]191 
[size=1em]192 
[size=1em]193 
[size=1em]194 
[size=1em]195 
[size=1em]196 
[size=1em]197 
[size=1em]198 
[size=1em]199 
[size=1em]200 
[size=1em]201 
[size=1em]202 
[size=1em]203 
[size=1em]204 
[size=1em]205 
[size=1em]206 
[size=1em]207 
[size=1em]208 
[size=1em]209 
[size=1em]210 
[size=1em]211 
[size=1em]212 
[size=1em]213 
[size=1em]214 
[size=1em]215 
[size=1em]216 
[size=1em]217 
[size=1em]218 
[size=1em]219 
[size=1em]220 
[size=1em]221 
[size=1em]222 
[size=1em]223 
[size=1em]224 
[size=1em]225 
[size=1em]226 
[size=1em]227 
[size=1em]228 
[size=1em]229 
[size=1em]230 
[size=1em]231 
[size=1em]232 
[size=1em]233 
[size=1em]234 
[size=1em]235 
[size=1em]236 
[size=1em]237 
[size=1em]238 
[size=1em]239 
[size=1em]240 
[size=1em]241 
[size=1em]242 
[size=1em]243 
[size=1em]244 
[size=1em]245 
[size=1em]246 
[size=1em]247 
[size=1em]248 
[size=1em]249 
[size=1em]250 
[size=1em]251 
[size=1em]252 
[size=1em]253 
[size=1em]254 
[size=1em]255 
[size=1em]256 
[size=1em]257 
[size=1em]258 
[size=1em]259 
[size=1em]260 
[size=1em]261 
[size=1em]262 
[size=1em]263 
[size=1em]264 
[size=1em]265 
[size=1em]266 
[size=1em]267 
[size=1em]268 
[size=1em]269 
[size=1em]270 
[size=1em]271 
[size=1em]272 
[size=1em]273 
[size=1em]274 
[size=1em]275 
[size=1em]276 
[size=1em]277 
[size=1em]278 
[size=1em]279 
[size=1em]280 
[size=1em]281 
[size=1em]282 
[size=1em]283 
[size=1em]284 
[size=1em]285 
[size=1em]286 
[size=1em]287 
[size=1em]288 
 | [size=1em][size=1em]#include <jni.h> 
[size=1em]#include <errno.h> 
 
[size=1em]#include <EGL/egl.h> 
[size=1em]#include <GLES/gl.h> 
 
[size=1em]#include <android/sensor.h> 
[size=1em]#include <android/log.h> 
[size=1em]#include <android_native_app_glue.h> 
 
[size=1em]#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__)) 
[size=1em]#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__)) 
 
[size=1em]/** 
[size=1em] * Our saved state data. 
[size=1em] */ 
[size=1em]struct saved_state { 
[size=1em]    float angle; 
[size=1em]    int32_t x; 
[size=1em]    int32_t y; 
[size=1em]}; 
 
[size=1em]/** 
[size=1em] * Shared state for our app. 
[size=1em] */ 
[size=1em]struct engine { 
[size=1em]    struct android_app* app; 
 
[size=1em]    ASensorManager* sensorManager; 
[size=1em]    const ASensor* accelerometerSensor; 
[size=1em]    ASensorEventQueue* sensorEventQueue; 
 
[size=1em]    int animating; 
[size=1em]    EGLDisplay display; 
[size=1em]    EGLSurface surface; 
[size=1em]    EGLContext context; 
[size=1em]    int32_t width; 
[size=1em]    int32_t height; 
[size=1em]    struct saved_state state; 
[size=1em]}; 
 
[size=1em]/** 
[size=1em] * Initialize an EGL context for the current display. 
[size=1em] */ 
[size=1em]static int engine_init_display(struct engine* engine) { 
[size=1em]    // initialize OpenGL ES and EGL 
 
[size=1em]    /* 
[size=1em]     * Here specify the attributes of the desired configuration. 
[size=1em]     * Below, we select an EGLConfig with at least 8 bits per color 
[size=1em]     * component compatible with on-screen windows 
[size=1em]     */ 
[size=1em]    const EGLint attribs[] = { 
[size=1em]            EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 
[size=1em]            EGL_BLUE_SIZE, 8, 
[size=1em]            EGL_GREEN_SIZE, 8, 
[size=1em]            EGL_RED_SIZE, 8, 
[size=1em]            EGL_NONE 
[size=1em]    }; 
[size=1em]    EGLint w, h, dummy, format; 
[size=1em]    EGLint numConfigs; 
[size=1em]    EGLConfig config; 
[size=1em]    EGLSurface surface; 
[size=1em]    EGLContext context; 
 
[size=1em]    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 
 
[size=1em]    eglInitialize(display, 0, 0); 
 
[size=1em]    /* Here, the application chooses the configuration it desires. In this 
[size=1em]     * sample, we have a very simplified selection process, where we pick 
[size=1em]     * the first EGLConfig that matches our criteria */ 
[size=1em]    eglChooseConfig(display, attribs, &config, 1, &numConfigs); 
 
[size=1em]    /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is 
[size=1em]     * guaranteed to be accepted by ANativeWindow_setBuffersGeometry(). 
[size=1em]     * As soon as we picked a EGLConfig, we can safely reconfigure the 
[size=1em]     * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */ 
[size=1em]    eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format); 
 
[size=1em]    ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format); 
 
[size=1em]    surface = eglCreateWindowSurface(display, config, engine->app->window, NULL); 
[size=1em]    context = eglCreateContext(display, config, NULL, NULL); 
 
[size=1em]    if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) { 
[size=1em]        LOGW("Unable to eglMakeCurrent"); 
[size=1em]        return -1; 
[size=1em]    } 
 
[size=1em]    eglQuerySurface(display, surface, EGL_WIDTH, &w); 
[size=1em]    eglQuerySurface(display, surface, EGL_HEIGHT, &h); 
 
[size=1em]    engine->display = display; 
[size=1em]    engine->context = context; 
[size=1em]    engine->surface = surface; 
[size=1em]    engine->width = w; 
[size=1em]    engine->height = h; 
[size=1em]    engine->state.angle = 0; 
 
[size=1em]    // Initialize GL state. 
[size=1em]    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); 
[size=1em]    glEnable(GL_CULL_FACE); 
[size=1em]    glShadeModel(GL_SMOOTH); 
[size=1em]    glDisable(GL_DEPTH_TEST); 
 
[size=1em]    return 0; 
[size=1em]} 
 
[size=1em]/** 
[size=1em] * Just the current frame in the display. 
[size=1em] */ 
[size=1em]static void engine_draw_frame(struct engine* engine) { 
[size=1em]    if (engine->display == NULL) { 
[size=1em]        // No display. 
[size=1em]        return; 
[size=1em]    } 
 
[size=1em]    // Just fill the screen with a color. 
[size=1em]    glClearColor(((float)engine->state.x)/engine->width, engine->state.angle, 
[size=1em]            ((float)engine->state.y)/engine->height, 1); 
[size=1em]    glClear(GL_COLOR_BUFFER_BIT); 
 
[size=1em]    eglSwapBuffers(engine->display, engine->surface); 
[size=1em]} 
 
[size=1em]/** 
[size=1em] * Tear down the EGL context currently associated with the display. 
[size=1em] */ 
[size=1em]static void engine_term_display(struct engine* engine) { 
[size=1em]    if (engine->display != EGL_NO_DISPLAY) { 
[size=1em]        eglMakeCurrent(engine->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 
[size=1em]        if (engine->context != EGL_NO_CONTEXT) { 
[size=1em]            eglDestroyContext(engine->display, engine->context); 
[size=1em]        } 
[size=1em]        if (engine->surface != EGL_NO_SURFACE) { 
[size=1em]            eglDestroySurface(engine->display, engine->surface); 
[size=1em]        } 
[size=1em]        eglTerminate(engine->display); 
[size=1em]    } 
[size=1em]    engine->animating = 0; 
[size=1em]    engine->display = EGL_NO_DISPLAY; 
[size=1em]    engine->context = EGL_NO_CONTEXT; 
[size=1em]    engine->surface = EGL_NO_SURFACE; 
[size=1em]} 
 
[size=1em]/** 
[size=1em] * Process the next input event. 
[size=1em] */ 
[size=1em]static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) { 
[size=1em]    struct engine* engine = (struct engine*)app->userData; 
[size=1em]    if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { 
[size=1em]        engine->animating = 1; 
[size=1em]        engine->state.x = AMotionEvent_getX(event, 0); 
[size=1em]        engine->state.y = AMotionEvent_getY(event, 0); 
[size=1em]        return 1; 
[size=1em]    } 
[size=1em]    return 0; 
[size=1em]} 
 
[size=1em]/** 
[size=1em] * Process the next main command. 
[size=1em] */ 
[size=1em]static void engine_handle_cmd(struct android_app* app, int32_t cmd) { 
[size=1em]    struct engine* engine = (struct engine*)app->userData; 
[size=1em]    switch (cmd) { 
[size=1em]        case APP_CMD_SAVE_STATE: 
[size=1em]            // The system has asked us to save our current state.  Do so. 
[size=1em]            engine->app->savedState = malloc(sizeof(struct saved_state)); 
[size=1em]            *((struct saved_state*)engine->app->savedState) = engine->state; 
[size=1em]            engine->app->savedStateSize = sizeof(struct saved_state); 
[size=1em]            break; 
[size=1em]        case APP_CMD_INIT_WINDOW: 
[size=1em]            // The window is being shown, get it ready. 
[size=1em]            if (engine->app->window != NULL) { 
[size=1em]                engine_init_display(engine); 
[size=1em]                engine_draw_frame(engine); 
[size=1em]            } 
[size=1em]            break; 
[size=1em]        case APP_CMD_TERM_WINDOW: 
[size=1em]            // The window is being hidden or closed, clean it up. 
[size=1em]            engine_term_display(engine); 
[size=1em]            break; 
[size=1em]        case APP_CMD_GAINED_FOCUS: 
[size=1em]            // When our app gains focus, we start monitoring the accelerometer. 
[size=1em]            if (engine->accelerometerSensor != NULL) { 
[size=1em]                ASensorEventQueue_enableSensor(engine->sensorEventQueue, 
[size=1em]                        engine->accelerometerSensor); 
[size=1em]                // We'd like to get 60 events per second (in us). 
[size=1em]                ASensorEventQueue_setEventRate(engine->sensorEventQueue, 
[size=1em]                        engine->accelerometerSensor, (1000L/60)*1000); 
[size=1em]            } 
[size=1em]            break; 
[size=1em]        case APP_CMD_LOST_FOCUS: 
[size=1em]            // When our app loses focus, we stop monitoring the accelerometer. 
[size=1em]            // This is to avoid consuming battery while not being used. 
[size=1em]            if (engine->accelerometerSensor != NULL) { 
[size=1em]                ASensorEventQueue_disableSensor(engine->sensorEventQueue, 
[size=1em]                        engine->accelerometerSensor); 
[size=1em]            } 
[size=1em]            // Also stop animating. 
[size=1em]            engine->animating = 0; 
[size=1em]            engine_draw_frame(engine); 
[size=1em]            break; 
[size=1em]    } 
[size=1em]} 
 
[size=1em]/** 
[size=1em] * This is the main entry point of a native application that is using 
[size=1em] * android_native_app_glue.  It runs in its own thread, with its own 
[size=1em] * event loop for receiving input events and doing other things. 
[size=1em] */ 
[size=1em]void android_main(struct android_app* state) { 
[size=1em]    struct engine engine; 
 
[size=1em]    // Make sure glue isn't stripped. 
[size=1em]    app_dummy(); 
 
[size=1em]    memset(&engine, 0, sizeof(engine)); 
[size=1em]    state->userData = &engine; 
[size=1em]    state->onAppCmd = engine_handle_cmd; 
[size=1em]    state->onInputEvent = engine_handle_input; 
[size=1em]    engine.app = state; 
 
[size=1em]    // Prepare to monitor accelerometer 
[size=1em]    engine.sensorManager = ASensorManager_getInstance(); 
[size=1em]    engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager, 
[size=1em]            ASENSOR_TYPE_ACCELEROMETER); 
[size=1em]    engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager, 
[size=1em]            state->looper, LOOPER_ID_USER, NULL, NULL); 
 
[size=1em]    if (state->savedState != NULL) { 
[size=1em]        // We are starting with a previous saved state; restore from it. 
[size=1em]        engine.state = *(struct saved_state*)state->savedState; 
[size=1em]    } 
 
[size=1em]    // loop waiting for stuff to do. 
 
[size=1em]    while (1) { 
[size=1em]        // Read all pending events. 
[size=1em]        int ident; 
[size=1em]        int events; 
[size=1em]        struct android_poll_source* source; 
 
[size=1em]        // If not animating, we will block forever waiting for events. 
[size=1em]        // If animating, we loop until all events are read, then continue 
[size=1em]        // to draw the next frame of animation. 
[size=1em]        while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events, 
[size=1em]                (void**)&source)) >= 0) { 
 
[size=1em]            // Process this event. 
[size=1em]            if (source != NULL) { 
[size=1em]                source->process(state, source); 
[size=1em]            } 
 
[size=1em]            // If a sensor has data, process it now. 
[size=1em]            if (ident == LOOPER_ID_USER) { 
[size=1em]                if (engine.accelerometerSensor != NULL) { 
[size=1em]                    ASensorEvent event; 
[size=1em]                    while (ASensorEventQueue_getEvents(engine.sensorEventQueue, 
[size=1em]                            &event, 1) > 0) { 
[size=1em]                        LOGI("accelerometer: x=%f y=%f z=%f", 
[size=1em]                                event.acceleration.x, event.acceleration.y, 
[size=1em]                                event.acceleration.z); 
[size=1em]                    } 
[size=1em]                } 
[size=1em]            } 
 
[size=1em]            // Check if we are exiting. 
[size=1em]            if (state->destroyRequested != 0) { 
[size=1em]                engine_term_display(&engine); 
[size=1em]                return; 
[size=1em]            } 
[size=1em]        } 
 
[size=1em]        if (engine.animating) { 
[size=1em]            // Done with events; draw next animation frame. 
[size=1em]            engine.state.angle += .01f; 
[size=1em]            if (engine.state.angle > 1) { 
[size=1em]                engine.state.angle = 0; 
[size=1em]            } 
 
[size=1em]            // Drawing is throttled to the screen update rate, so there 
[size=1em]            // is no need to do timing here. 
[size=1em]            engine_draw_frame(&engine); 
[size=1em]        } 
[size=1em]    } 
[size=1em]} 
 
  |