diff --git a/android/bifrost.c b/android/bifrost.c deleted file mode 100644 index 50bffa97ef..0000000000 --- a/android/bifrost.c +++ /dev/null @@ -1,178 +0,0 @@ -/* RetroArch - A frontend for libretro. - * Copyright (C) 2010-2012 - Hans-Kristian Arntzen - * Copyright (C) 2011-2012 - Daniel De Matteis - * - * RetroArch is free software: you can redistribute it and/or modify it under the terms - * of the GNU General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with RetroArch. - * If not, see . - */ - -/* RetroArch Bifrost: - * A burning rainbow bridge that reaches between Java (the world) - * and C/C++, the realm of the gods */ - -#include -#include -#include "../boolean.h" - -#include "com_retroarch_rruntime.h" - -#include "../console/rarch_console.h" -#include "../../console/rarch_console_config.h" -#include "../console/rarch_console_main_wrap.h" -#include "../console/rarch_console_rom_ext.h" -#include "../console/rarch_console_settings.h" -#include "../console/rarch_console_input.h" -#include "../console/rarch_console_video.h" -#include "../general.h" -#include "../conf/config_file.h" -#include "../conf/config_file_macros.h" -#include "../file.h" - -JNIEXPORT jint JNICALL JNI_OnLoad( JavaVM *vm, void *pvt) -{ - RARCH_LOG("JNI_OnLoad.\n" ); - - rarch_main_clear_state(); - - config_set_defaults(); - input_null.init(); - - RARCH_LOG("JNI_OnLoad #1.\n" ); - - const input_driver_t *input = &input_null; - - bool find_libretro_file = false; - - snprintf(default_paths.config_file, sizeof(default_paths.config_file), "/mnt/extsd/retroarch.cfg"); - - RARCH_LOG("JNI_OnLoad #1.1.\n" ); - - rarch_init_msg_queue(); - - RARCH_LOG("JNI_OnLoad #1.2.\n" ); - - rarch_settings_set_default(); - - RARCH_LOG("JNI_OnLoad #1.3.\n" ); - //rarch_input_set_controls_default(input); - rarch_config_load(default_paths.config_file, find_libretro_file); - - RARCH_LOG("JNI_OnLoad #1.4.\n" ); - init_libretro_sym(); - - RARCH_LOG("JNI_OnLoad #1.5.\n" ); - - - input_null.post_init(); - RARCH_LOG("JNI_OnLoad #1.6.\n" ); - - //video_gl.start(); - - RARCH_LOG("JNI_OnLoad #1.7.\n" ); - - //driver.video = &video_gl; - - RARCH_LOG("JNI_OnLoad #1.8.\n" ); - - RARCH_LOG("Reached end of JNI_OnLoad.\n" ); - - return JNI_VERSION_1_2; -} - -JNIEXPORT void JNICALL JNI_OnUnLoad( JavaVM *vm, void *pvt) -{ - RARCH_LOG("JNI_OnUnLoad.\n" ); -} - -JNIEXPORT void JNICALL Java_com_retroarch_rruntime_load_1game - (JNIEnv *env, jclass class, jstring j_path, jint j_extract_zip_mode) -{ - jboolean is_copy = false; - const char * game_path = (*env)->GetStringUTFChars(env, j_path, &is_copy); - RARCH_LOG("rruntime_load_game: %s.\n", game_path); - - rarch_console_load_game_wrap(game_path, 0, 0); - - (*env)->ReleaseStringUTFChars(env, j_path, game_path); -} - -static int counter = 0; - -JNIEXPORT jboolean JNICALL Java_com_retroarch_rruntime_run_1frame - (JNIEnv *env, jclass class) -{ - counter++; - RARCH_LOG("counter: %d.\n", counter); - return rarch_main_iterate(); -} - -JNIEXPORT void JNICALL Java_com_retroarch_rruntime_startup - (JNIEnv *env, jclass class, jstring j_config_path) -{ - bool retval = false; - jboolean is_copy = false; - const char * config_path = (*env)->GetStringUTFChars(env, j_config_path, &is_copy); - - RARCH_LOG("rruntime_startup (config file: %s).\n", config_path); - - retval = rarch_startup(config_path); - - rarch_init_msg_queue(); - - (*env)->ReleaseStringUTFChars(env, j_config_path, config_path); -} - -JNIEXPORT void JNICALL Java_com_retroarch_rruntime_deinit - (JNIEnv *env, jclass class) -{ - rarch_main_deinit(); -} - -JNIEXPORT void JNICALL Java_com_retroarch_rruntime_load_1state - (JNIEnv *env, jclass class) -{ - rarch_load_state(); -} - -JNIEXPORT void JNICALL Java_com_retroarch_rruntime_save_1state - (JNIEnv *env, jclass class) -{ - rarch_save_state(); -} - -JNIEXPORT void JNICALL Java_com_retroarch_rruntime_settings_1change - (JNIEnv *env, jclass class, jint j_setting) -{ - unsigned setting = j_setting; - rarch_settings_change(setting); -} - -JNIEXPORT void JNICALL Java_com_retroarch_rruntime_settings_1set_1defaults - (JNIEnv *env, jclass class) -{ - RARCH_LOG("* rruntime_settings_set_defaults.\n" ); - rarch_settings_set_default(); -} - -void gfx_ctx_set_window(JNIEnv *jenv,jobject obj, jobject surface); -void gfx_ctx_free_window(JNIEnv *jenv,jobject obj, jobject surface); - -JNIEXPORT void JNICALL Java_com_retroarch_rruntime_set_window - (JNIEnv *env, jclass class, jobject obj, jobject surface) -{ - gfx_ctx_set_window(env, obj, surface); -} - -JNIEXPORT void JNICALL Java_com_retroarch_rruntime_free_window - (JNIEnv *env, jclass class, jobject obj, jobject surface) -{ - gfx_ctx_free_window(env, obj, surface); -} diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 2ddcdb0d5a..acc182a206 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -6,10 +6,48 @@ include $(CLEAR_VARS) APP_OPTIM := debug LOCAL_MODULE := retroarch -LOCAL_SRC_FILES = ../../console/griffin/griffin.c ../../console/rzlib/rzlib.c ../bifrost.c +LOCAL_SRC_FILES = ../../retroarch.c \ + ../../file.c \ + ../../file_path.c \ + ../../hash.c \ + ../../driver.c \ + ../../settings.c \ + ../../dynamic.c \ + ../../message.c \ + ../../rewind.c \ + ../../gfx/gfx_common.c \ + ../../input/input_common.c \ + ../../patch.c \ + ../../fifo_buffer.c \ + ../../compat/compat.c \ + ../../audio/null.c \ + ../../audio/utils.c \ + ../../audio/hermite.c \ + ../../gfx/null.c \ + ../../gfx/gl.c \ + ../../gfx/scaler/scaler.c \ + ../../gfx/scaler/pixconv.c \ + ../../gfx/scaler/scaler_int.c \ + ../../gfx/scaler/filter.c \ + ../../gfx/gfx_context.c \ + ../../gfx/context/androidegl_ctx.c \ + ../../gfx/math/matrix.c \ + ../../gfx/shader_glsl.c \ + ../../gfx/fonts/null_fonts.c \ + ../../gfx/state_tracker.c \ + ../../input/null.c \ + ../../screenshot.c \ + ../../conf/config_file.c \ + ../../autosave.c \ + ../../thread.c \ + ../../console/rzlib/rzlib.c \ + main.c -LOCAL_CFLAGS = -DPERF_TEST -marm -DANDROID -DHAVE_DYNAMIC -DHAVE_DYLIB -DHAVE_OPENGL -DHAVE_OPENGLES -DHAVE_OPENGLES2 -DHAVE_GLSL -DHAVE_VID_CONTEXT -DHAVE_ZLIB -DHAVE_RARCH_MAIN_WRAP -DINLINE=inline -DRARCH_CONSOLE -DLSB_FIRST -D__LIBRETRO__ -DHAVE_CONFIGFILE=1 -DHAVE_GRIFFIN=1 -DPACKAGE_VERSION=\"$(RARCH_VERSION)\" -Dmain=rarch_main -std=gnu99 +LOCAL_CFLAGS = -marm -DANDROID -DHAVE_DYNAMIC -DHAVE_OPENGL -DHAVE_OPENGLES -DHAVE_OPENGLES2 -DHAVE_GLSL -DHAVE_ZLIB -DHAVE_RARCH_MAIN_WRAP -DINLINE=inline -DLSB_FIRST -D__LIBRETRO__ -DHAVE_CONFIGFILE=1 -DPACKAGE_VERSION=\"$(RARCH_VERSION)\" -std=gnu99 LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -landroid -lEGL -lGLESv2 -llog -ldl -lz +LOCAL_STATIC_LIBRARIES := android_native_app_glue include $(BUILD_SHARED_LIBRARY) + +$(call import-module,android/native_app_glue) diff --git a/android/jni/main.c b/android/jni/main.c new file mode 100644 index 0000000000..75391de305 --- /dev/null +++ b/android/jni/main.c @@ -0,0 +1,322 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2012 - Hans-Kristian Arntzen + * Copyright (C) 2011-2012 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "../../general.h" + +JNIEXPORT jint JNICALL JNI_OnLoad( JavaVM *vm, void *pvt) +{ + RARCH_LOG("JNI_OnLoad.\n" ); + + return JNI_VERSION_1_2; +} + +JNIEXPORT void JNICALL JNI_OnUnLoad( JavaVM *vm, void *pvt) +{ + RARCH_LOG("JNI_OnUnLoad.\n" ); +} + +/** + * Our saved state data. + */ +struct saved_state +{ + float angle; + int32_t x; + int32_t y; +}; + +/** + * Shared state for our app. + */ +struct engine +{ + struct android_app* app; + + ASensorManager* sensorManager; + const ASensor* accelerometerSensor; + ASensorEventQueue* sensorEventQueue; + + int animating; + EGLDisplay display; + EGLSurface surface; + EGLContext context; + int32_t width; + int32_t height; + struct saved_state state; +}; + +/** + * Initialize an EGL context for the current display. + */ +static int engine_init_display(struct engine* engine) +{ + // initialize OpenGL ES and EGL + + const EGLint attribs[] = + { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_BLUE_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_RED_SIZE, 8, + EGL_NONE + }; + EGLint w, h, dummy, format; + EGLint numConfigs; + EGLConfig config; + EGLSurface surface; + EGLContext context; + + EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + + eglInitialize(display, 0, 0); + + /* Here, the application chooses the configuration it desires. In this + * sample, we have a very simplified selection process, where we pick + * the first EGLConfig that matches our criteria */ + eglChooseConfig(display, attribs, &config, 1, &numConfigs); + + /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is + * guaranteed to be accepted by ANativeWindow_setBuffersGeometry(). + * As soon as we picked a EGLConfig, we can safely reconfigure the + * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */ + eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format); + + ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format); + + surface = eglCreateWindowSurface(display, config, engine->app->window, NULL); + context = eglCreateContext(display, config, NULL, NULL); + + if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) + { + RARCH_ERR("Unable to eglMakeCurrent.\n"); + return -1; + } + + eglQuerySurface(display, surface, EGL_WIDTH, &w); + eglQuerySurface(display, surface, EGL_HEIGHT, &h); + + engine->display = display; + engine->context = context; + engine->surface = surface; + engine->width = w; + engine->height = h; + engine->state.angle = 0; + + // Initialize GL state. + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + glEnable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + + return 0; +} + +/** + * Just the current frame in the display. + */ +static void engine_draw_frame(struct engine* engine) +{ + if (engine->display == NULL) + return; + + // Just fill the screen with a color. + glClearColor(((float)engine->state.x)/engine->width, engine->state.angle, + ((float)engine->state.y)/engine->height, 1); + + glClear(GL_COLOR_BUFFER_BIT); + + eglSwapBuffers(engine->display, engine->surface); +} + +/** + * Tear down the EGL context currently associated with the display. + */ +static void engine_term_display(struct engine* engine) +{ + if (engine->display != EGL_NO_DISPLAY) + { + eglMakeCurrent(engine->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + + if (engine->context != EGL_NO_CONTEXT) + eglDestroyContext(engine->display, engine->context); + if (engine->surface != EGL_NO_SURFACE) + eglDestroySurface(engine->display, engine->surface); + + eglTerminate(engine->display); + } + engine->animating = 0; + engine->display = EGL_NO_DISPLAY; + engine->context = EGL_NO_CONTEXT; + engine->surface = EGL_NO_SURFACE; +} + +/** + * Process the next input event. + */ +static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) +{ + struct engine* engine = (struct engine*)app->userData; + + if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) + { + engine->animating = 1; + engine->state.x = AMotionEvent_getX(event, 0); + engine->state.y = AMotionEvent_getY(event, 0); + return 1; + } + return 0; +} + +/** + * Process the next main command. + */ +static void engine_handle_cmd(struct android_app* app, int32_t cmd) +{ + struct engine* engine = (struct engine*)app->userData; + + switch (cmd) + { + case APP_CMD_SAVE_STATE: + // The system has asked us to save our current state. Do so. + engine->app->savedState = malloc(sizeof(struct saved_state)); + *((struct saved_state*)engine->app->savedState) = engine->state; + engine->app->savedStateSize = sizeof(struct saved_state); + break; + case APP_CMD_INIT_WINDOW: + // The window is being shown, get it ready. + if (engine->app->window != NULL) + { + engine_init_display(engine); + engine_draw_frame(engine); + } + break; + case APP_CMD_TERM_WINDOW: + // The window is being hidden or closed, clean it up. + engine_term_display(engine); + break; + case APP_CMD_GAINED_FOCUS: + // When our app gains focus, we start monitoring the accelerometer. + if (engine->accelerometerSensor != NULL) + { + ASensorEventQueue_enableSensor(engine->sensorEventQueue, + engine->accelerometerSensor); + + // We'd like to get 60 events per second (in us). + ASensorEventQueue_setEventRate(engine->sensorEventQueue, + engine->accelerometerSensor, (1000L/60)*1000); + } + break; + case APP_CMD_LOST_FOCUS: + // When our app loses focus, we stop monitoring the accelerometer. + // This is to avoid consuming battery while not being used. + if (engine->accelerometerSensor != NULL) + ASensorEventQueue_disableSensor(engine->sensorEventQueue, + engine->accelerometerSensor); + // Also stop animating. + engine->animating = 0; + engine_draw_frame(engine); + break; + } +} + +/** + * This is the main entry point of a native application that is using + * android_native_app_glue. It runs in its own thread, with its own + * event loop for receiving input events and doing other things. + */ +void android_main(struct android_app* state) +{ + struct engine engine; + + // Make sure glue isn't stripped. + app_dummy(); + + memset(&engine, 0, sizeof(engine)); + state->userData = &engine; + state->onAppCmd = engine_handle_cmd; + state->onInputEvent = engine_handle_input; + engine.app = state; + + // Prepare to monitor accelerometer + engine.sensorManager = ASensorManager_getInstance(); + engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager, + ASENSOR_TYPE_ACCELEROMETER); + engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager, + state->looper, LOOPER_ID_USER, NULL, NULL); + + if (state->savedState != NULL) // We are starting with a previous saved state; restore from it. + engine.state = *(struct saved_state*)state->savedState; + + // loop waiting for stuff to do. + + while (1) + { + // Read all pending events. + int ident; + int events; + struct android_poll_source* source; + + // If not animating, we will block forever waiting for events. + // If animating, we loop until all events are read, then continue + // to draw the next frame of animation. + while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events, + (void**)&source)) >= 0) + { + // Process this event. + if (source != NULL) + source->process(state, source); + + // If a sensor has data, process it now. + if (ident == LOOPER_ID_USER && engine.accelerometerSensor != NULL) + { + ASensorEvent event; + while (ASensorEventQueue_getEvents(engine.sensorEventQueue, &event, 1) > 0) + RARCH_WARN("accelerometer: x=%f y=%f z=%f.\n", event.acceleration.x, + event.acceleration.y, event.acceleration.z); + } + + // Check if we are exiting. + if (state->destroyRequested != 0) + { + engine_term_display(&engine); + return; + } + } + + if (engine.animating) + { + // Done with events; draw next animation frame. + engine.state.angle += .01f; + + if (engine.state.angle > 1) + engine.state.angle = 0; + + // Drawing is throttled to the screen update rate, so there + // is no need to do timing here. + engine_draw_frame(&engine); + } + } +} diff --git a/gfx/context/androidegl_ctx.c b/gfx/context/androidegl_ctx.c index baae97e56f..e07f96f26c 100644 --- a/gfx/context/androidegl_ctx.c +++ b/gfx/context/androidegl_ctx.c @@ -340,6 +340,7 @@ const gfx_ctx_driver_t gfx_ctx_android = { NULL, "android", +#ifdef RARCH_CONSOLE // RARCH_CONSOLE stuff. gfx_ctx_set_filtering, gfx_ctx_get_available_resolutions, @@ -353,4 +354,5 @@ const gfx_ctx_driver_t gfx_ctx_android = { gfx_ctx_set_fbo, gfx_ctx_apply_fbo_state_changes, +#endif }; diff --git a/gfx/gl.c b/gfx/gl.c index 4d9ff85283..338280eb32 100644 --- a/gfx/gl.c +++ b/gfx/gl.c @@ -38,7 +38,7 @@ #include "shader_cg.h" #endif -#ifdef HAVE_XML +#if defined(HAVE_XML) || defined(HAVE_GLSL) #include "shader_glsl.h" #endif diff --git a/input/input_common.c b/input/input_common.c index 504a5f124a..942b70bf32 100644 --- a/input/input_common.c +++ b/input/input_common.c @@ -29,7 +29,7 @@ static const rarch_joypad_driver_t *joypad_drivers[] = { #ifdef HAVE_SDL &sdl_joypad, #endif -#ifdef __linux +#if defined(__linux) && !defined(ANDROID) &linuxraw_joypad, #endif };