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