| /* //device/apps/Quake/quake/src/QW/client/main.c |
| ** |
| ** Copyright 2007, The Android Open Source Project |
| ** |
| ** Licensed under the Apache License, Version 2.0 (the "License"); |
| ** you may not use this file except in compliance with the License. |
| ** You may obtain a copy of the License at |
| ** |
| ** http://www.apache.org/licenses/LICENSE-2.0 |
| ** |
| ** Unless required by applicable law or agreed to in writing, software |
| ** distributed under the License is distributed on an "AS IS" BASIS, |
| ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| ** See the License for the specific language governing permissions and |
| ** limitations under the License. |
| */ |
| |
| #include <jni.h> |
| #include <stdio.h> |
| #include <assert.h> |
| |
| #if !defined(__GDK__) |
| #include <bcc/bcc.h> |
| #include <dlfcn.h> |
| #endif |
| |
| #include <android/log.h> |
| #include "sys.h" |
| |
| #define LOG_TAG "Quake masterMain" |
| #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) |
| #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) |
| |
| #if !defined(__GDK__) |
| int AndroidInit(); |
| int AndroidEvent2(int type, int value); |
| int AndroidMotionEvent(unsigned long long eventTime, int action, float x, float y, float pressure, float size, int deviceId); |
| int AndroidTrackballEvent(unsigned long long eventTime, int action, float x, float y); |
| int AndroidStep(int width, int height); |
| void AndroidQuit(); |
| |
| typedef int (*pAndroidInitType)(); |
| typedef int (*pAndroidEvent2Type)(int type, int value); |
| typedef int (*pAndroidMotionEventType)(unsigned long long eventTime, int action, float x, float y, float pressure, float size, int deviceId); |
| typedef int (*pAndroidTrackballEventType)(unsigned long long eventTime, int action, float x, float y); |
| typedef int (*pAndroidStepType)(int width, int height); |
| typedef void (*pAndroidQuitType)(); |
| |
| static pAndroidInitType pAndroidInit; |
| static pAndroidEvent2Type pAndroidEvent2; |
| static pAndroidMotionEventType pAndroidMotionEvent; |
| static pAndroidTrackballEventType pAndroidTrackballEvent; |
| static pAndroidStepType pAndroidStep; |
| static pAndroidQuitType pAndroidQuit; |
| |
| static int use_llvm = 1; |
| |
| jboolean |
| qinit(JNIEnv *env, jobject thiz) { |
| LOGI("qinit"); |
| return pAndroidInit() ? JNI_TRUE : JNI_FALSE; |
| } |
| |
| jboolean |
| qevent(JNIEnv *env, jobject thiz, jint type, jint value) { |
| return pAndroidEvent2(type, value) ? JNI_TRUE : JNI_FALSE; |
| } |
| |
| jboolean |
| qmotionevent(JNIEnv *env, jobject thiz, jlong eventTime, jint action, |
| jfloat x, jfloat y, jfloat pressure, jfloat size, jint deviceId) { |
| return pAndroidMotionEvent((unsigned long long) eventTime, |
| action, x, y, pressure, size, |
| deviceId) ? JNI_TRUE : JNI_FALSE; |
| } |
| |
| jboolean |
| qtrackballevent(JNIEnv *env, jobject thiz, jlong eventTime, jint action, |
| jfloat x, jfloat y) { |
| return pAndroidTrackballEvent((unsigned long long) eventTime, |
| action, x, y) ? JNI_TRUE : JNI_FALSE; |
| } |
| |
| jboolean |
| qstep(JNIEnv *env, jobject thiz, jint width, jint height) { |
| return pAndroidStep(width, height) ? JNI_TRUE : JNI_FALSE; |
| } |
| |
| void |
| qquit(JNIEnv *env, jobject thiz) { |
| LOGI("qquit"); |
| return pAndroidQuit(); |
| } |
| |
| jboolean |
| gdk(JNIEnv *env, jobject obj) |
| { |
| #if !defined(__NOGDK__) |
| return JNI_TRUE; |
| #else |
| return JNI_FALSE; |
| #endif |
| } |
| |
| #if !defined(__GDK__) && !defined(__NOGDK__) |
| static void* lookupSymbol(void* pContext, const char* name) |
| { |
| return (void*) dlsym(RTLD_DEFAULT, name); |
| } |
| #endif // !__GDK__ && !__NOGDK__ |
| |
| jboolean |
| qcompile_bc(JNIEnv *env, jobject thiz, jbyteArray scriptRef, jint length) |
| { |
| #if !defined(__GDK__) && !defined(__NOGDK__) |
| if (!use_llvm) |
| return JNI_TRUE; |
| |
| pAndroidInitType new_pAndroidInit; |
| pAndroidEvent2Type new_pAndroidEvent2; |
| pAndroidMotionEventType new_pAndroidMotionEvent; |
| pAndroidTrackballEventType new_pAndroidTrackballEvent; |
| pAndroidStepType new_pAndroidStep; |
| pAndroidQuitType new_pAndroidQuit; |
| int all_func_found = 1; |
| |
| double time = Sys_FloatTime (); |
| |
| BCCScriptRef script_ref = bccCreateScript(); |
| jbyte* script_ptr = (jbyte *)env->GetPrimitiveArrayCritical(scriptRef, (jboolean *)0); |
| LOGI("BCC Script Len: %d", length); |
| if (bccReadBC(script_ref, "libquake_portable.bc", (const char*)script_ptr, length, 0)) { |
| LOGE("Error! Cannot bccReadBc"); |
| return JNI_FALSE; |
| } |
| if (script_ptr) { |
| env->ReleasePrimitiveArrayCritical(scriptRef, script_ptr, 0); |
| } |
| #if 0 |
| if (bccLinkFile(script_ref, "/system/lib/libclcore.bc", 0)) { |
| LOGE("Error! Cannot bccLinkBC"); |
| return JNI_FALSE; |
| } |
| #endif |
| |
| double newtime = Sys_FloatTime (); |
| double readtime = newtime - time; |
| time = newtime; |
| |
| bccRegisterSymbolCallback(script_ref, lookupSymbol, NULL); |
| |
| #ifdef OLD_BCC |
| if (bccPrepareExecutable(script_ref, "/data/data/com.android.quake.llvm/quakeLLVM.oBCC", 0)) { |
| LOGE("Error! Cannot bccPrepareExecutable"); |
| return JNI_FALSE; |
| } |
| #else |
| if (bccPrepareExecutable(script_ref, "/data/data/com.android.quake.llvm/", "quakeLLVM", 0)) { |
| LOGE("Error! Cannot bccPrepareExecutable"); |
| return JNI_FALSE; |
| } |
| #endif // OLD_BCC |
| |
| newtime = Sys_FloatTime (); |
| double compiletime = newtime - time; |
| time = newtime; |
| |
| new_pAndroidInit = (pAndroidInitType)bccGetFuncAddr(script_ref, "AndroidInit_LLVM"); |
| if (new_pAndroidInit == NULL) { |
| LOGE("Error! Cannot find AndroidInit_LLVM()"); |
| all_func_found = 0; |
| //return JNI_FALSE; |
| } |
| LOGI("Found AndroidInit_LLVM() @ 0x%x", (unsigned)new_pAndroidInit); |
| |
| new_pAndroidEvent2 = (pAndroidEvent2Type)bccGetFuncAddr(script_ref, "AndroidEvent2_LLVM"); |
| if (new_pAndroidEvent2 == NULL) { |
| LOGE("Error! Cannot find AndroidEvent2_LLVM()"); |
| all_func_found = 0; |
| //return JNI_FALSE; |
| } |
| LOGI("Found AndroidEvent2_LLVM() @ 0x%x", (unsigned)new_pAndroidEvent2); |
| |
| new_pAndroidMotionEvent = (pAndroidMotionEventType)bccGetFuncAddr(script_ref, "AndroidMotionEvent_LLVM"); |
| if (new_pAndroidMotionEvent == NULL) { |
| LOGE("Error! Cannot find AndroidMotionEvent_LLVM()"); |
| all_func_found = 0; |
| //return JNI_FALSE; |
| } |
| LOGI("Found AndroidMotionEvent_LLVM() @ 0x%x", (unsigned)new_pAndroidMotionEvent); |
| |
| new_pAndroidTrackballEvent = (pAndroidTrackballEventType)bccGetFuncAddr(script_ref, "AndroidTrackballEvent_LLVM"); |
| if (new_pAndroidTrackballEvent == NULL) { |
| LOGE("Error! Cannot find AndroidTrackballEvent_LLVM()"); |
| all_func_found = 0; |
| //return JNI_FALSE; |
| } |
| LOGI("Found AndroidTrackballEvent_LLVM() @ 0x%x", (unsigned)new_pAndroidTrackballEvent); |
| |
| new_pAndroidStep = (pAndroidStepType)bccGetFuncAddr(script_ref, "AndroidStep_LLVM"); |
| if (new_pAndroidStep == NULL) { |
| LOGE("Error! Cannot find AndroidStep_LLVM()"); |
| all_func_found = 0; |
| //return JNI_FALSE; |
| } |
| LOGI("Found AndroidStep_LLVM() @ 0x%x", (unsigned)new_pAndroidStep); |
| |
| new_pAndroidQuit = (pAndroidQuitType)bccGetFuncAddr(script_ref, "AndroidQuit_LLVM"); |
| if (new_pAndroidQuit == NULL) { |
| LOGE("Error! Cannot find AndroidQuit_LLVM()"); |
| all_func_found = 0; |
| //return JNI_FALSE; |
| } |
| LOGI("Found AndroidQuit_LLVM() @ 0x%x", (unsigned)new_pAndroidQuit); |
| |
| //bccDisposeScript(script_ref); |
| |
| if (all_func_found) |
| { |
| LOGI("Use LLVM version"); |
| pAndroidInit = new_pAndroidInit; |
| pAndroidEvent2 = new_pAndroidEvent2; |
| pAndroidMotionEvent = new_pAndroidMotionEvent; |
| pAndroidTrackballEvent = new_pAndroidTrackballEvent; |
| pAndroidStep = new_pAndroidStep; |
| pAndroidQuit = new_pAndroidQuit; |
| } |
| newtime = Sys_FloatTime (); |
| double findptrtime = newtime - time; |
| |
| LOGI("LLVM JIT time = %lf (%lf + %lf + %lf)\n", readtime+compiletime+findptrtime, |
| readtime, compiletime, findptrtime); |
| |
| return JNI_TRUE; |
| #else |
| |
| return JNI_FALSE; |
| |
| #endif // !__GDK__ && !__NOGDK__ |
| } |
| |
| |
| static const char *classPathName = "com/android/quake/llvm/QuakeLib"; |
| |
| static JNINativeMethod methods[] = { |
| {"gdk", "()Z", (void*)gdk }, |
| {"compile_bc", "([BI)Z", (void*)qcompile_bc }, |
| {"init", "()Z", (void*)qinit }, |
| {"event", "(II)Z", (void*)qevent }, |
| {"motionEvent", "(JIFFFFI)Z", (void*) qmotionevent }, |
| {"trackballEvent", "(JIFF)Z", (void*) qtrackballevent }, |
| {"step", "(II)Z", (void*)qstep }, |
| {"quit", "()V", (void*)qquit }, |
| }; |
| |
| /* |
| * Register several native methods for one class. |
| */ |
| static int registerNativeMethods(JNIEnv* env, const char* className, |
| JNINativeMethod* gMethods, int numMethods) |
| { |
| jclass clazz; |
| |
| clazz = env->FindClass(className); |
| if (clazz == NULL) { |
| fprintf(stderr, |
| "Native registration unable to find class '%s'\n", className); |
| return JNI_FALSE; |
| } |
| if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) { |
| fprintf(stderr, "RegisterNatives failed for '%s'\n", className); |
| return JNI_FALSE; |
| } |
| |
| return JNI_TRUE; |
| } |
| |
| /* |
| * Register native methods for all classes we know about. |
| */ |
| static int registerNatives(JNIEnv* env) |
| { |
| if (!registerNativeMethods(env, classPathName, |
| methods, sizeof(methods) / sizeof(methods[0]))) { |
| return JNI_FALSE; |
| } |
| |
| return JNI_TRUE; |
| } |
| |
| /* |
| * Set some test stuff up. |
| * |
| * Returns the JNI version on success, -1 on failure. |
| */ |
| |
| typedef union { |
| JNIEnv* env; |
| void* venv; |
| } UnionJNIEnvToVoid; |
| |
| jint JNI_OnLoad(JavaVM* vm, void* reserved) |
| { |
| UnionJNIEnvToVoid uenv; |
| uenv.venv = NULL; |
| jint result = -1; |
| JNIEnv* env = NULL; |
| |
| if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) { |
| fprintf(stderr, "ERROR: GetEnv failed\n"); |
| goto bail; |
| } |
| env = uenv.env; |
| |
| assert(env != NULL); |
| |
| printf("In mgmain JNI_OnLoad\n"); |
| |
| if (!registerNatives(env)) { |
| fprintf(stderr, "ERROR: quakemaster native registration failed\n"); |
| goto bail; |
| } |
| |
| /* success -- return valid version number */ |
| result = JNI_VERSION_1_4; |
| |
| pAndroidInit = AndroidInit; |
| pAndroidEvent2 = AndroidEvent2; |
| pAndroidMotionEvent = AndroidMotionEvent; |
| pAndroidTrackballEvent = AndroidTrackballEvent; |
| pAndroidStep = AndroidStep; |
| pAndroidQuit = AndroidQuit; |
| |
| bail: |
| return result; |
| } |
| |
| |
| #endif // __GDK__ |