diff --git a/common/backends.h b/common/backends.h index 77bcced8..6fd51f19 100644 --- a/common/backends.h +++ b/common/backends.h @@ -18,21 +18,17 @@ GNU General Public License for more details. // video backends (XASH_VIDEO) #define VIDEO_NULL 0 #define VIDEO_SDL 1 -#define VIDEO_ANDROID 2 #define VIDEO_FBDEV 3 #define VIDEO_DOS 4 - // audio backends (XASH_SOUND) #define SOUND_NULL 0 #define SOUND_SDL 1 -#define SOUND_OPENSLES 2 #define SOUND_ALSA 3 // input (XASH_INPUT) #define INPUT_NULL 0 #define INPUT_SDL 1 -#define INPUT_ANDROID 2 #define INPUT_EVDEV 3 // timer (XASH_TIMER) @@ -45,16 +41,13 @@ GNU General Public License for more details. // messageboxes (XASH_MESSAGEBOX) #define MSGBOX_STDERR 0 #define MSGBOX_SDL 1 -#define MSGBOX_ANDROID 2 #define MSGBOX_WIN32 3 #define MSGBOX_NSWITCH 4 - // library loading (XASH_LIB) #define LIB_NULL 0 #define LIB_POSIX 1 #define LIB_WIN32 2 #define LIB_STATIC 3 - #endif /* BACKENDS_H */ diff --git a/common/defaults.h b/common/defaults.h index c99edcaa..a3e57295 100644 --- a/common/defaults.h +++ b/common/defaults.h @@ -52,26 +52,6 @@ SETUP BACKENDS DEFINITIONS #endif #endif // XASH_MESSAGEBOX #endif - #elif XASH_ANDROID - // we are building for Android platform, use Android APIs - #ifndef XASH_VIDEO - #define XASH_VIDEO VIDEO_ANDROID - #endif // XASH_VIDEO - - #ifndef XASH_INPUT - #define XASH_INPUT INPUT_ANDROID - #endif // XASH_INPUT - - #ifndef XASH_SOUND - #define XASH_SOUND SOUND_OPENSLES - #endif // XASH_SOUND - - #ifndef XASH_MESSAGEBOX - #define XASH_MESSAGEBOX MSGBOX_ANDROID - #endif // XASH_MESSAGEBOX - - #define XASH_USE_EVDEV 1 - #define XASH_DYNAMIC_DLADDR #elif XASH_LINUX // we are building for Linux without SDL2, can draw only to framebuffer yet #ifndef XASH_VIDEO @@ -171,6 +151,8 @@ Default build-depended cvar and constant values #define DEFAULT_MODE_WIDTH 960 #define DEFAULT_MODE_HEIGHT 544 #define DEFAULT_ALLOWCONSOLE 1 +#elif XASH_ANDROID + #define DEFAULT_TOUCH_ENABLE "1" #elif XASH_MOBILE_PLATFORM #define DEFAULT_TOUCH_ENABLE "1" #define DEFAULT_M_IGNORE "1" diff --git a/engine/client/input.c b/engine/client/input.c index 12cede03..71017882 100644 --- a/engine/client/input.c +++ b/engine/client/input.c @@ -179,9 +179,6 @@ void IN_ToggleClientMouse( int newstate, int oldstate ) { Platform_SetCursorType( dc_arrow ); -#if XASH_ANDROID - Android_ShowMouse( true ); -#endif #if XASH_USE_EVDEV Evdev_SetGrab( false ); #endif @@ -190,9 +187,6 @@ void IN_ToggleClientMouse( int newstate, int oldstate ) { Platform_SetCursorType( dc_none ); -#if XASH_ANDROID - Android_ShowMouse( false ); -#endif #if XASH_USE_EVDEV Evdev_SetGrab( true ); #endif diff --git a/engine/platform/android/android.c b/engine/platform/android/android.c deleted file mode 100644 index 5a61bccf..00000000 --- a/engine/platform/android/android.c +++ /dev/null @@ -1,993 +0,0 @@ -/* -android_nosdl.c - android backend -Copyright (C) 2016-2019 mittorn - -This program 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 Foundation, either version 3 of the License, or -(at your option) any later version. - -This program 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. -*/ -#include "platform/platform.h" -#if !defined(XASH_DEDICATED) -#include "input.h" -#include "client.h" -#include "sound.h" -#include "platform/android/android_priv.h" -#include "errno.h" -#include -#include - -#ifndef JNICALL -#define JNICALL // a1ba: workaround for my IDE, where Java files are not included -#define JNIEXPORT -#endif - -convar_t *android_sleep; - -static const int s_android_scantokey[] = -{ - 0, K_LEFTARROW, K_RIGHTARROW, K_AUX26, K_ESCAPE, // 0 - K_AUX26, K_AUX25, '0', '1', '2', // 5 - '3', '4', '5', '6', '7', // 10 - '8', '9', '*', '#', K_UPARROW, // 15 - K_DOWNARROW, K_LEFTARROW, K_RIGHTARROW, K_ENTER, K_AUX32, // 20 - K_AUX31, K_AUX29, K_AUX28, K_AUX27, 'a', // 25 - 'b', 'c', 'd', 'e', 'f', // 30 - 'g', 'h', 'i', 'j', 'k', // 35 - 'l', 'm', 'n', 'o', 'p', // 40 - 'q', 'r', 's', 't', 'u', // 45 - 'v', 'w', 'x', 'y', 'z', // 50 - ',', '.', K_ALT, K_ALT, K_SHIFT, // 55 - K_SHIFT, K_TAB, K_SPACE, 0, 0, // 60 - 0, K_ENTER, K_BACKSPACE, '`', '-', // 65 - '=', '[', ']', '\\', ';', // 70 - '\'', '/', '@', K_KP_NUMLOCK, 0, // 75 - 0, '+', '`', 0, 0, // 80 - 0, 0, 0, 0, 0, // 85 - 0, 0, K_PGUP, K_PGDN, 0, // 90 - 0, K_AUX1, K_AUX2, K_AUX14, K_AUX3, // 95 - K_AUX4, K_AUX15, K_AUX6, K_AUX7, K_JOY1, // 100 - K_JOY2, K_AUX10, K_AUX11, K_ESCAPE, K_ESCAPE, // 105 - 0, K_ESCAPE, K_DEL, K_CTRL, K_CTRL, // 110 - K_CAPSLOCK, 0, 0, 0, 0, // 115 - 0, K_PAUSE, K_HOME, K_END, K_INS, // 120 - 0, 0, 0, 0, 0, // 125 - 0, K_F1, K_F2, K_F3, K_F4, // 130 - K_F5, K_F6, K_F7, K_F8, K_F9, // 135 - K_F10, K_F11, K_F12, K_KP_NUMLOCK, K_KP_INS, // 140 - K_KP_END, K_KP_DOWNARROW, K_KP_PGDN, K_KP_LEFTARROW, K_KP_5, // 145 - K_KP_RIGHTARROW,K_KP_HOME, K_KP_UPARROW, K_KP_PGUP, K_KP_SLASH, // 150 - 0, K_KP_MINUS, K_KP_PLUS, K_KP_DEL, ',', // 155 - K_KP_ENTER, '=', '(', ')' -}; - -#define ANDROID_MAX_EVENTS 64 -#define MAX_FINGERS 10 - -typedef enum event_type -{ - event_touch_down = 0, - event_touch_up, - event_touch_move, // compatible with touchEventType - event_key_down, - event_key_up, - event_set_pause, - event_resize, - event_joyhat, - event_joyball, - event_joybutton, - event_joyaxis, - event_joyadd, - event_joyremove, - event_onpause, - event_ondestroy, - event_onresume, - event_onfocuschange, -} eventtype_t; - -typedef struct touchevent_s -{ - float x; - float y; - float dx; - float dy; -} touchevent_t; - -typedef struct joyball_s -{ - short xrel; - short yrel; - byte ball; -} joyball_t; - -typedef struct joyhat_s -{ - byte hat; - byte key; -} joyhat_t; - -typedef struct joyaxis_s -{ - short val; - byte axis; -} joyaxis_t; - -typedef struct joybutton_s -{ - int down; - byte button; -} joybutton_t; - -typedef struct keyevent_s -{ - int code; -} keyevent_t; - -typedef struct event_s -{ - eventtype_t type; - int arg; - union - { - touchevent_t touch; - joyhat_t hat; - joyball_t ball; - joyaxis_t axis; - joybutton_t button; - keyevent_t key; - }; -} event_t; - -typedef struct finger_s -{ - float x, y; - qboolean down; -} finger_t; - -static struct { - pthread_mutex_t mutex; // this mutex is locked while not running frame, used for events synchronization - pthread_mutex_t framemutex; // this mutex is locked while engine is running and unlocked while it reading events, used for pause in background. - event_t queue[ANDROID_MAX_EVENTS]; - volatile int count; - finger_t fingers[MAX_FINGERS]; - char inputtext[256]; - float mousex, mousey; -} events = { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER }; - -struct jnimethods_s jni; -struct jnimouse_s jnimouse; - -#define Android_Lock() pthread_mutex_lock(&events.mutex); -#define Android_Unlock() pthread_mutex_unlock(&events.mutex); -#define Android_PushEvent() Android_Unlock() - -typedef void (*pfnChangeGame)( const char *progname ); -int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGame, pfnChangeGame func ); - -/* -======================== -Android_AllocEvent - -Lock event queue and return pointer to next event. -Caller must do Android_PushEvent() to unlock queue after setting parameters. -======================== -*/ -event_t *Android_AllocEvent( void ) -{ - Android_Lock(); - if( events.count == ANDROID_MAX_EVENTS ) - { - events.count--; //override last event - __android_log_print( ANDROID_LOG_ERROR, "Xash", "Too many events!!!" ); - } - return &events.queue[ events.count++ ]; -} - - -/* -===================================================== -JNI callbacks - -On application start, setenv and onNativeResize called from -ui thread to set up engine configuration -nativeInit called directly from engine thread and will not return until exit. -These functions may be called from other threads at any time: -nativeKey -nativeTouch -onNativeResize -nativeString -nativeSetPause -===================================================== -*/ -#define VA_ARGS(...) , ##__VA_ARGS__ // GCC extension -#define DECLARE_JNI_INTERFACE( ret, name, ... ) \ - JNIEXPORT ret JNICALL Java_su_xash_engine_XashActivity_##name( JNIEnv *env, jclass clazz VA_ARGS(__VA_ARGS__) ) - -DECLARE_JNI_INTERFACE( int, nativeInit, jobject array ) -{ - int i; - int argc; - int status; - /* Prepare the arguments. */ - - int len = (*env)->GetArrayLength(env, array); - char** argv = calloc( 1 + len + 1, sizeof( char ** )); - argc = 0; - argv[argc++] = strdup("app_process"); - for (i = 0; i < len; ++i) { - const char* utf; - char* arg = NULL; - jstring string = (*env)->GetObjectArrayElement(env, array, i); - if (string) { - utf = (*env)->GetStringUTFChars(env, string, 0); - if (utf) { - arg = strdup(utf); - (*env)->ReleaseStringUTFChars(env, string, utf); - } - (*env)->DeleteLocalRef(env, string); - } - if (!arg) { - arg = strdup(""); - } - argv[argc++] = arg; - } - argv[argc] = NULL; - prctl(PR_SET_DUMPABLE, 1); - - /* Init callbacks. */ - - jni.env = env; - jni.actcls = (*env)->FindClass(env, "su/xash/engine/XashActivity"); - jni.enableTextInput = (*env)->GetStaticMethodID(env, jni.actcls, "showKeyboard", "(I)V"); - jni.vibrate = (*env)->GetStaticMethodID(env, jni.actcls, "vibrate", "(I)V" ); - jni.messageBox = (*env)->GetStaticMethodID(env, jni.actcls, "messageBox", "(Ljava/lang/String;Ljava/lang/String;)V"); - jni.notify = (*env)->GetStaticMethodID(env, jni.actcls, "engineThreadNotify", "()V"); - jni.setTitle = (*env)->GetStaticMethodID(env, jni.actcls, "setTitle", "(Ljava/lang/String;)V"); - jni.setIcon = (*env)->GetStaticMethodID(env, jni.actcls, "setIcon", "(Ljava/lang/String;)V"); - jni.getAndroidId = (*env)->GetStaticMethodID(env, jni.actcls, "getAndroidID", "()Ljava/lang/String;"); - jni.saveID = (*env)->GetStaticMethodID(env, jni.actcls, "saveID", "(Ljava/lang/String;)V"); - jni.loadID = (*env)->GetStaticMethodID(env, jni.actcls, "loadID", "()Ljava/lang/String;"); - jni.showMouse = (*env)->GetStaticMethodID(env, jni.actcls, "showMouse", "(I)V"); - jni.shellExecute = (*env)->GetStaticMethodID(env, jni.actcls, "shellExecute", "(Ljava/lang/String;)V"); - - jni.swapBuffers = (*env)->GetStaticMethodID(env, jni.actcls, "swapBuffers", "()V"); - jni.toggleEGL = (*env)->GetStaticMethodID(env, jni.actcls, "toggleEGL", "(I)V"); - jni.createGLContext = (*env)->GetStaticMethodID(env, jni.actcls, "createGLContext", "([I[I)Z"); - jni.getGLAttribute = (*env)->GetStaticMethodID(env, jni.actcls, "getGLAttribute", "(I)I"); - jni.deleteGLContext = (*env)->GetStaticMethodID(env, jni.actcls, "deleteGLContext", "()Z"); - jni.getSelectedPixelFormat = (*env)->GetStaticMethodID(env, jni.actcls, "getSelectedPixelFormat", "()I"); - jni.getSurface = (*env)->GetStaticMethodID(env, jni.actcls, "getNativeSurface", "()Landroid/view/Surface;"); - - /* Run the application. */ - - status = Host_Main( argc, argv, getenv("XASH3D_GAMEDIR"), false, NULL ); - - /* Release the arguments. */ - - for (i = 0; i < argc; ++i) - free(argv[i]); - free(argv); - - return status; -} - -DECLARE_JNI_INTERFACE( void, onNativeResize, jint width, jint height ) -{ - event_t *event; - - if( !width || !height ) - return; - - jni.width=width, jni.height=height; - - // alloc update event to change screen size - event = Android_AllocEvent(); - event->type = event_resize; - Android_PushEvent(); -} - -DECLARE_JNI_INTERFACE( void, nativeQuit ) -{ -} - -DECLARE_JNI_INTERFACE( void, nativeSetPause, jint pause ) -{ - event_t *event = Android_AllocEvent(); - event->type = event_set_pause; - event->arg = pause; - Android_PushEvent(); - - // if pause enabled, hold engine by locking frame mutex. - // Engine will stop after event reading and will not continue untill unlock - if( android_sleep && android_sleep->value ) - { - if( pause ) - pthread_mutex_lock( &events.framemutex ); - else - pthread_mutex_unlock( &events.framemutex ); - } -} - -DECLARE_JNI_INTERFACE( void, nativeUnPause ) -{ - // UnPause engine before sending critical events - if( android_sleep && android_sleep->value ) - pthread_mutex_unlock( &events.framemutex ); -} - -DECLARE_JNI_INTERFACE( void, nativeKey, jint down, jint code ) -{ - event_t *event; - - if( code < 0 ) - { - event = Android_AllocEvent(); - event->arg = (-code) & 255; - event->type = down?event_key_down:event_key_up; - Android_PushEvent(); - } - else - { - if( code >= ( sizeof( s_android_scantokey ) / sizeof( s_android_scantokey[0] ) ) ) - { - Con_DPrintf( "nativeKey: unknown Android key %d\n", code ); - return; - } - - if( !s_android_scantokey[code] ) - { - Con_DPrintf( "nativeKey: unmapped Android key %d\n", code ); - return; - } - - event = Android_AllocEvent(); - event->type = down?event_key_down:event_key_up; - event->arg = s_android_scantokey[code]; - Android_PushEvent(); - } -} - -DECLARE_JNI_INTERFACE( void, nativeString, jobject string ) -{ - char* str = (char *) (*env)->GetStringUTFChars(env, string, NULL); - - Android_Lock(); - strncat( events.inputtext, str, 256 ); - Android_Unlock(); - - (*env)->ReleaseStringUTFChars(env, string, str); -} - -#ifdef SOFTFP_LINK -DECLARE_JNI_INTERFACE( void, nativeTouch, jint finger, jint action, jfloat x, jfloat y ) __attribute__((pcs("aapcs"))); -#endif -DECLARE_JNI_INTERFACE( void, nativeTouch, jint finger, jint action, jfloat x, jfloat y ) -{ - float dx, dy; - event_t *event; - - // if something wrong with android event - if( finger > MAX_FINGERS ) - return; - - // not touch action? - if( !( action >=0 && action <= 2 ) ) - return; - - // 0.0f .. 1.0f - x /= jni.width; - y /= jni.height; - - if( action ) - dx = x - events.fingers[finger].x, dy = y - events.fingers[finger].y; - else - dx = dy = 0.0f; - events.fingers[finger].x = x, events.fingers[finger].y = y; - - // check if we should skip some events - if( ( action == 2 ) && ( !dx && !dy ) ) - return; - - if( ( action == 0 ) && events.fingers[finger].down ) - return; - - if( ( action == 1 ) && !events.fingers[finger].down ) - return; - - if( action == 2 && !events.fingers[finger].down ) - action = 0; - - if( action == 0 ) - events.fingers[finger].down = true; - else if( action == 1 ) - events.fingers[finger].down = false; - - event = Android_AllocEvent(); - event->arg = finger; - event->type = action; - event->touch.x = x; - event->touch.y = y; - event->touch.dx = dx; - event->touch.dy = dy; - Android_PushEvent(); -} - -DECLARE_JNI_INTERFACE( void, nativeBall, jint id, jbyte ball, jshort xrel, jshort yrel ) -{ - event_t *event = Android_AllocEvent(); - - event->type = event_joyball; - event->arg = id; - event->ball.ball = ball; - event->ball.xrel = xrel; - event->ball.yrel = yrel; - Android_PushEvent(); -} - -DECLARE_JNI_INTERFACE( void, nativeHat, jint id, jbyte hat, jbyte key, jboolean down ) -{ - event_t *event = Android_AllocEvent(); - static byte engineKeys; - - if( !key ) - engineKeys = 0; // centered; - - if( down ) - engineKeys |= key; - else - engineKeys &= ~key; - - event->type = event_joyhat; - event->arg = id; - event->hat.hat = hat; - event->hat.key = engineKeys; - Android_PushEvent(); -} - -DECLARE_JNI_INTERFACE( void, nativeAxis, jint id, jbyte axis, jshort val ) -{ - event_t *event = Android_AllocEvent(); - event->type = event_joyaxis; - event->arg = id; - event->axis.axis = axis; - event->axis.val = val; - - __android_log_print(ANDROID_LOG_VERBOSE, "Xash", "axis %i %i", axis, val ); - Android_PushEvent(); -} - -DECLARE_JNI_INTERFACE( void, nativeJoyButton, jint id, jbyte button, jboolean down ) -{ - event_t *event = Android_AllocEvent(); - event->type = event_joybutton; - event->arg = id; - event->button.button = button; - event->button.down = down; - __android_log_print(ANDROID_LOG_VERBOSE, "Xash", "button %i", button ); - Android_PushEvent(); -} - -DECLARE_JNI_INTERFACE( void, nativeJoyAdd, jint id ) -{ - event_t *event = Android_AllocEvent(); - event->type = event_joyadd; - event->arg = id; - Android_PushEvent(); -} - -DECLARE_JNI_INTERFACE( void, nativeJoyDel, jint id ) -{ - event_t *event = Android_AllocEvent(); - event->type = event_joyremove; - event->arg = id; - Android_PushEvent(); -} - -DECLARE_JNI_INTERFACE( void, nativeOnResume ) -{ - event_t *event = Android_AllocEvent(); - event->type = event_onresume; - Android_PushEvent(); -} - -DECLARE_JNI_INTERFACE( void, nativeOnFocusChange ) -{ - event_t *event = Android_AllocEvent(); - event->type = event_onfocuschange; - Android_PushEvent(); -} - -DECLARE_JNI_INTERFACE( void, nativeOnPause ) -{ - event_t *event = Android_AllocEvent(); - event->type = event_onpause; - Android_PushEvent(); -} - -DECLARE_JNI_INTERFACE( void, nativeOnDestroy ) -{ - event_t *event = Android_AllocEvent(); - event->type = event_ondestroy; - Android_PushEvent(); -} - -DECLARE_JNI_INTERFACE( int, setenv, jstring key, jstring value, jboolean overwrite ) -{ - char* k = (char *) (*env)->GetStringUTFChars(env, key, NULL); - char* v = (char *) (*env)->GetStringUTFChars(env, value, NULL); - int err = setenv(k, v, overwrite); - (*env)->ReleaseStringUTFChars(env, key, k); - (*env)->ReleaseStringUTFChars(env, value, v); - return err; -} - - -DECLARE_JNI_INTERFACE( void, nativeMouseMove, jfloat x, jfloat y ) -{ - Android_Lock(); - events.mousex += x; - events.mousey += y; - Android_Unlock(); -} - -DECLARE_JNI_INTERFACE( int, nativeTestWritePermission, jstring jPath ) -{ - char *path = (char *)(*env)->GetStringUTFChars(env, jPath, NULL); - FILE *fd; - char testFile[PATH_MAX]; - int ret = 0; - - // maybe generate new file everytime? - Q_snprintf( testFile, PATH_MAX, "%s/.testfile", path ); - - __android_log_print( ANDROID_LOG_VERBOSE, "Xash", "nativeTestWritePermission: file=%s", testFile ); - - fd = fopen( testFile, "w+" ); - - if( fd ) - { - __android_log_print( ANDROID_LOG_VERBOSE, "Xash", "nativeTestWritePermission: passed" ); - ret = 1; - fclose( fd ); - - remove( testFile ); - } - else - { - __android_log_print( ANDROID_LOG_VERBOSE, "Xash", "nativeTestWritePermission: error=%s", strerror( errno ) ); - } - - (*env)->ReleaseStringUTFChars( env, jPath, path ); - - return ret; -} - -JNIEXPORT jint JNICALL JNI_OnLoad( JavaVM *vm, void *reserved ) -{ - return JNI_VERSION_1_6; -} - -/* -======================== -Platform_Init - -Initialize android-related cvars -======================== -*/ -void Platform_Init( void ) -{ - android_sleep = Cvar_Get( "android_sleep", "1", FCVAR_ARCHIVE, "Enable sleep in background" ); -} - -void Platform_Shutdown( void ) -{ - -} - -/* -======================== -Android_EnableTextInput - -Show virtual keyboard -======================== -*/ -void Platform_EnableTextInput( qboolean enable ) -{ - (*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.enableTextInput, enable ); -} - -/* -======================== -Android_Vibrate -======================== -*/ -void Platform_Vibrate( float life, char flags ) -{ - if( life ) - (*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.vibrate, (int)life ); -} - -/* -======================== -Android_GetNativeObject -======================== -*/ -void *Platform_GetNativeObject( const char *objName ) -{ - static const char *availObjects[] = { "JNIEnv", "ActivityClass", NULL }; - void *object = NULL; - - if( !objName ) - { - object = (void*)availObjects; - } - else if( !strcasecmp( objName, "JNIEnv" ) ) - { - object = (void*)jni.env; - } - else if( !strcasecmp( objName, "ActivityClass" ) ) - { - object = (void*)jni.actcls; - } - - return object; -} - -/* -======================== -Android_MessageBox - -Show messagebox and wait for OK button press -======================== -*/ -#if XASH_MESSAGEBOX == MSGBOX_ANDROID -void Platform_MessageBox( const char *title, const char *text, qboolean parentMainWindow ) -{ - (*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.messageBox, (*jni.env)->NewStringUTF( jni.env, title ), (*jni.env)->NewStringUTF( jni.env ,text ) ); -} -#endif // XASH_MESSAGEBOX == MSGBOX_ANDROID - -/* -======================== -Android_GetAndroidID -======================== -*/ -const char *Android_GetAndroidID( void ) -{ - static char id[65]; - const char *resultCStr; - jstring resultJNIStr; - - if( id[0] ) - return id; - - resultJNIStr = (jstring)(*jni.env)->CallStaticObjectMethod( jni.env, jni.actcls, jni.getAndroidId ); - resultCStr = (*jni.env)->GetStringUTFChars( jni.env, resultJNIStr, NULL ); - Q_strncpy( id, resultCStr, 64 ); - (*jni.env)->ReleaseStringUTFChars( jni.env, resultJNIStr, resultCStr ); - - if( !id[0] ) - return NULL; - - return id; -} - -/* -======================== -Android_LoadID -======================== -*/ -const char *Android_LoadID( void ) -{ - static char id[65]; - jstring resultJNIStr = (jstring)(*jni.env)->CallStaticObjectMethod( jni.env, jni.actcls, jni.loadID ); - const char *resultCStr = (*jni.env)->GetStringUTFChars( jni.env, resultJNIStr, NULL ); - Q_strncpy( id, resultCStr, 64 ); - (*jni.env)->ReleaseStringUTFChars( jni.env, resultJNIStr, resultCStr ); - return id; -} - -/* -======================== -Android_SaveID -======================== -*/ -void Android_SaveID( const char *id ) -{ - (*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.saveID, (*jni.env)->NewStringUTF( jni.env, id ) ); -} - -/* -======================== -Android_MouseMove -======================== -*/ -void Platform_MouseMove( float *x, float *y ) -{ - *x = jnimouse.x; - *y = jnimouse.y; - jnimouse.x = 0; - jnimouse.y = 0; - // Con_Reportf( "Android_MouseMove: %f %f\n", *x, *y ); -} - -/* -======================== -Android_AddMove -======================== -*/ -void Android_AddMove( float x, float y ) -{ - jnimouse.x += x; - jnimouse.y += y; -} - -void GAME_EXPORT Platform_GetMousePos( int *x, int *y ) -{ - // stub -} - -void GAME_EXPORT Platform_SetMousePos( int x, int y ) -{ - // stub -} - -int Platform_JoyInit( int numjoy ) -{ - // stub - return 0; -} - -/* -======================== -Android_ShowMouse -======================== -*/ -void Android_ShowMouse( qboolean show ) -{ - if( m_ignore->value ) - show = true; - (*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.showMouse, show ); -} - -/* -======================== -Android_ShellExecute -======================== -*/ -void Platform_ShellExecute( const char *path, const char *parms ) -{ - jstring jstr; - - if( !path ) - return; // useless - - // get java.lang.String - jstr = (*jni.env)->NewStringUTF( jni.env, path ); - - // open browser - (*jni.env)->CallStaticVoidMethod(jni.env, jni.actcls, jni.shellExecute, jstr); - - // no need to free jstr -} - -int Platform_GetClipboardText( char *buffer, size_t size ) -{ - // stub - if( size ) buffer[0] = 0; - return 0; -} - -void Platform_SetClipboardText( const char *buffer ) -{ - // stub -} - -void Platform_SetCursorType( VGUI_DefaultCursor cursor ) -{ - // stub -} - -key_modifier_t Platform_GetKeyModifiers( void ) -{ - // stub - return KeyModifier_None; -} - -void Platform_PreCreateMove( void ) -{ - // stub -} - -/* -======================== -Android_RunEvents - -Execute all events from queue -======================== -*/ -void Platform_RunEvents( void ) -{ - int i; - - // enter events read - Android_Lock(); - pthread_mutex_unlock( &events.framemutex ); - - for( i = 0; i < events.count; i++ ) - { - switch( events.queue[i].type ) - { - case event_touch_down: - case event_touch_up: - case event_touch_move: - IN_TouchEvent( (touchEventType)events.queue[i].type, events.queue[i].arg, - events.queue[i].touch.x, events.queue[i].touch.y, - events.queue[i].touch.dx, events.queue[i].touch.dy ); - break; - - case event_key_down: - Key_Event( events.queue[i].arg, true ); - - if( events.queue[i].arg == K_AUX31 || events.queue[i].arg == K_AUX29 ) - { - host.force_draw_version = true; - host.force_draw_version_time = host.realtime + FORCE_DRAW_VERSION_TIME; - } - break; - case event_key_up: - Key_Event( events.queue[i].arg, false ); - - if( events.queue[i].arg == K_AUX31 || events.queue[i].arg == K_AUX29 ) - { - host.force_draw_version = true; - host.force_draw_version_time = host.realtime + FORCE_DRAW_VERSION_TIME; - } - break; - - case event_set_pause: - // destroy EGL surface when hiding application - if( !events.queue[i].arg ) - { - SNDDMA_Activate( true ); -// (*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.toggleEGL, 1 ); - Android_UpdateSurface( true ); - host.status = HOST_FRAME; - SetBits( gl_vsync->flags, FCVAR_CHANGED ); // set swap interval - host.force_draw_version = true; - host.force_draw_version_time = host.realtime + FORCE_DRAW_VERSION_TIME; - } - - if( events.queue[i].arg ) - { - SNDDMA_Activate( false ); - Android_UpdateSurface( false ); - host.status = HOST_NOFOCUS; -// (*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.toggleEGL, 0 ); - } - break; - - case event_resize: - // reinitialize EGL and change engine screen size - if( host.status == HOST_FRAME &&( refState.width != jni.width || refState.height != jni.height ) ) - { -// (*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.toggleEGL, 0 ); -// (*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.toggleEGL, 1 ); - Android_UpdateSurface( true ); - SetBits( gl_vsync->flags, FCVAR_CHANGED ); // set swap interval - VID_SetMode(); - } - break; - case event_joyadd: - Joy_AddEvent(); - break; - case event_joyremove: - Joy_RemoveEvent(); - break; - case event_joyball: - if( !Joy_IsActive() ) - Joy_AddEvent(); - Joy_BallMotionEvent( events.queue[i].ball.ball, - events.queue[i].ball.xrel, events.queue[i].ball.yrel ); - break; - case event_joyhat: - if( !Joy_IsActive() ) - Joy_AddEvent(); - Joy_HatMotionEvent( events.queue[i].hat.hat, events.queue[i].hat.key ); - break; - case event_joyaxis: - if( !Joy_IsActive() ) - Joy_AddEvent(); - Joy_AxisMotionEvent( events.queue[i].axis.axis, events.queue[i].axis.val ); - break; - case event_joybutton: - if( !Joy_IsActive() ) - Joy_AddEvent(); - Joy_ButtonEvent( events.queue[i].button.button, (byte)events.queue[i].button.down ); - break; - case event_ondestroy: - //host.skip_configs = true; // skip config save, because engine may be killed during config save - Sys_Quit(); - (*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.notify ); - break; - case event_onpause: -#ifdef PARANOID_CONFIG_SAVE - switch( host.status ) - { - case HOST_INIT: - case HOST_CRASHED: - case HOST_ERR_FATAL: - Con_Reportf( S_WARN "Abnormal host state during onPause (%d), skipping config save!\n", host.status ); - break; - default: - // restore all latched cheat cvars - Cvar_SetCheatState( true ); - Host_WriteConfig(); - } -#endif - // disable sound during call/screen-off - SNDDMA_Activate( false ); -// host.status = HOST_NOFOCUS; - // stop blocking UI thread - (*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.notify ); - - break; - case event_onresume: - // re-enable sound after onPause -// host.status = HOST_FRAME; - SNDDMA_Activate( true ); - host.force_draw_version = true; - host.force_draw_version_time = host.realtime + FORCE_DRAW_VERSION_TIME; - break; - case event_onfocuschange: - host.force_draw_version = true; - host.force_draw_version_time = host.realtime + FORCE_DRAW_VERSION_TIME; - break; - } - } - - events.count = 0; // no more events - - // text input handled separately to allow unicode symbols - for( i = 0; events.inputtext[i]; i++ ) - { - int ch; - - // if engine does not use utf-8, we need to convert it to preferred encoding - if( !Q_stricmp( cl_charset->string, "utf-8" ) ) - ch = (unsigned char)events.inputtext[i]; - else - ch = Con_UtfProcessCharForce( (unsigned char)events.inputtext[i] ); - - if( !ch ) // utf-8 - continue; - - // some keyboards may send enter as text - if( ch == '\n' ) - { - Key_Event( K_ENTER, true ); - Key_Event( K_ENTER, false ); - continue; - } - - // otherwise just push it by char, text render will decode unicode strings - CL_CharEvent( ch ); - } - events.inputtext[0] = 0; // no more text - - jnimouse.x += events.mousex; - events.mousex = 0; - jnimouse.y += events.mousey; - events.mousey = 0; - - //end events read - Android_Unlock(); - pthread_mutex_lock( &events.framemutex ); -} - -#endif // XASH_DEDICATED diff --git a/engine/platform/android/android_priv.h b/engine/platform/android/android_priv.h deleted file mode 100644 index 3af27197..00000000 --- a/engine/platform/android/android_priv.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once -#ifndef ANDROID_PRIV_H -#define ANDROID_PRIV_H - -#include -#include -#include - -extern struct jnimethods_s -{ - jclass actcls; - JavaVM *vm; - JNIEnv *env; - jmethodID enableTextInput; - jmethodID vibrate; - jmethodID messageBox; - jmethodID notify; - jmethodID setTitle; - jmethodID setIcon; - jmethodID getAndroidId; - jmethodID saveID; - jmethodID loadID; - jmethodID showMouse; - jmethodID shellExecute; - jmethodID swapBuffers; - jmethodID toggleEGL; - jmethodID createGLContext; - jmethodID getGLAttribute; - jmethodID deleteGLContext; - jmethodID getSelectedPixelFormat; - jmethodID getSurface; - int width, height; -} jni; - - -extern struct jnimouse_s -{ - float x, y; -} jnimouse; - -// -// vid_android.c -// -void Android_UpdateSurface( qboolean active ); - -#endif // ANDROID_PRIV_H diff --git a/engine/platform/android/snd_opensles.c b/engine/platform/android/snd_opensles.c deleted file mode 100644 index 4cf5bbe0..00000000 --- a/engine/platform/android/snd_opensles.c +++ /dev/null @@ -1,277 +0,0 @@ -/* -Copyright (C) 2015 SiPlus, Chasseur de bots - -This program 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 Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#include "common.h" -#include "platform/platform.h" -#if XASH_SOUND == SOUND_OPENSLES -#include -#include "pthread.h" -#include "sound.h" - -extern dma_t dma; - -static SLObjectItf snddma_android_engine = NULL; -static SLObjectItf snddma_android_outputMix = NULL; -static SLObjectItf snddma_android_player = NULL; -static SLBufferQueueItf snddma_android_bufferQueue; -static SLPlayItf snddma_android_play; - -static pthread_mutex_t snddma_android_mutex = PTHREAD_MUTEX_INITIALIZER; - -static int snddma_android_size; - -static const SLInterfaceID *pSL_IID_ENGINE; -static const SLInterfaceID *pSL_IID_BUFFERQUEUE; -static const SLInterfaceID *pSL_IID_PLAY; -static SLresult SLAPIENTRY (*pslCreateEngine)( - SLObjectItf *pEngine, - SLuint32 numOptions, - const SLEngineOption *pEngineOptions, - SLuint32 numInterfaces, - const SLInterfaceID *pInterfaceIds, - const SLboolean * pInterfaceRequired -); - -void SNDDMA_Activate( qboolean active ) -{ - if( !dma.initialized ) - return; - - if( active ) - { - memset( dma.buffer, 0, snddma_android_size * 2 ); - (*snddma_android_bufferQueue)->Enqueue( snddma_android_bufferQueue, dma.buffer, snddma_android_size ); - (*snddma_android_play)->SetPlayState( snddma_android_play, SL_PLAYSTATE_PLAYING ); - } - else - { - (*snddma_android_play)->SetPlayState( snddma_android_play, SL_PLAYSTATE_STOPPED ); - (*snddma_android_bufferQueue)->Clear( snddma_android_bufferQueue ); - } -} - -static void SNDDMA_Android_Callback( SLBufferQueueItf bq, void *context ) -{ - uint8_t *buffer2; - - pthread_mutex_lock( &snddma_android_mutex ); - - buffer2 = ( uint8_t * )dma.buffer + snddma_android_size; - (*bq)->Enqueue( bq, buffer2, snddma_android_size ); - memcpy( buffer2, dma.buffer, snddma_android_size ); - memset( dma.buffer, 0, snddma_android_size ); - dma.samplepos += dma.samples; - - pthread_mutex_unlock( &snddma_android_mutex ); -} - -static const char *SNDDMA_Android_Init( void ) -{ - SLresult result; - - SLEngineItf engine; - - int freq; - - SLDataLocator_BufferQueue sourceLocator; - SLDataFormat_PCM sourceFormat; - SLDataSource source; - - SLDataLocator_OutputMix sinkLocator; - SLDataSink sink; - - SLInterfaceID interfaceID; - SLboolean interfaceRequired; - - int samples; - void *handle = dlopen( "libOpenSLES.so", RTLD_LAZY ); - - if( !handle ) - return "dlopen for libOpenSLES.so"; - - pslCreateEngine = dlsym( handle, "slCreateEngine" ); - - if( !pslCreateEngine ) - return "resolve slCreateEngine"; - - pSL_IID_ENGINE = dlsym( handle, "SL_IID_ENGINE" ); - - if( !pSL_IID_ENGINE ) - return "resolve SL_IID_ENGINE"; - - pSL_IID_PLAY = dlsym( handle, "SL_IID_PLAY" ); - - if( !pSL_IID_PLAY ) - return "resolve SL_IID_PLAY"; - - pSL_IID_BUFFERQUEUE = dlsym( handle, "SL_IID_BUFFERQUEUE" ); - - if( !pSL_IID_BUFFERQUEUE ) - return "resolve SL_IID_BUFFERQUEUE"; - - - result = pslCreateEngine( &snddma_android_engine, 0, NULL, 0, NULL, NULL ); - if( result != SL_RESULT_SUCCESS ) return "slCreateEngine"; - result = (*snddma_android_engine)->Realize( snddma_android_engine, SL_BOOLEAN_FALSE ); - if( result != SL_RESULT_SUCCESS ) return "engine->Realize"; - result = (*snddma_android_engine)->GetInterface( snddma_android_engine, *pSL_IID_ENGINE, &engine ); - if( result != SL_RESULT_SUCCESS ) return "engine->GetInterface(ENGINE)"; - - result = (*engine)->CreateOutputMix( engine, &snddma_android_outputMix, 0, NULL, NULL ); - if( result != SL_RESULT_SUCCESS ) return "engine->CreateOutputMix"; - result = (*snddma_android_outputMix)->Realize( snddma_android_outputMix, SL_BOOLEAN_FALSE ); - if( result != SL_RESULT_SUCCESS ) return "outputMix->Realize"; - - freq = SOUND_DMA_SPEED; - sourceLocator.locatorType = SL_DATALOCATOR_BUFFERQUEUE; - sourceLocator.numBuffers = 2; - sourceFormat.formatType = SL_DATAFORMAT_PCM; - sourceFormat.numChannels = 2; // always stereo, because engine supports only stereo - sourceFormat.samplesPerSec = freq * 1000; - sourceFormat.bitsPerSample = 16; // always 16 bit audio - sourceFormat.containerSize = sourceFormat.bitsPerSample; - sourceFormat.channelMask = SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT; - sourceFormat.endianness = SL_BYTEORDER_LITTLEENDIAN; - source.pLocator = &sourceLocator; - source.pFormat = &sourceFormat; - - sinkLocator.locatorType = SL_DATALOCATOR_OUTPUTMIX; - sinkLocator.outputMix = snddma_android_outputMix; - sink.pLocator = &sinkLocator; - sink.pFormat = NULL; - - interfaceID = *pSL_IID_BUFFERQUEUE; - interfaceRequired = SL_BOOLEAN_TRUE; - - result = (*engine)->CreateAudioPlayer( engine, &snddma_android_player, &source, &sink, 1, &interfaceID, &interfaceRequired ); - if( result != SL_RESULT_SUCCESS ) return "engine->CreateAudioPlayer"; - result = (*snddma_android_player)->Realize( snddma_android_player, SL_BOOLEAN_FALSE ); - if( result != SL_RESULT_SUCCESS ) return "player->Realize"; - result = (*snddma_android_player)->GetInterface( snddma_android_player, *pSL_IID_BUFFERQUEUE, &snddma_android_bufferQueue ); - if( result != SL_RESULT_SUCCESS ) return "player->GetInterface(BUFFERQUEUE)"; - result = (*snddma_android_player)->GetInterface( snddma_android_player, *pSL_IID_PLAY, &snddma_android_play ); - if( result != SL_RESULT_SUCCESS ) return "player->GetInterface(PLAY)"; - result = (*snddma_android_bufferQueue)->RegisterCallback( snddma_android_bufferQueue, SNDDMA_Android_Callback, NULL ); - if( result != SL_RESULT_SUCCESS ) return "bufferQueue->RegisterCallback"; - - samples = s_samplecount.value; - if( !samples ) - samples = 4096; - - dma.format.channels = sourceFormat.numChannels; - dma.samples = samples * sourceFormat.numChannels; - dma.format.speed = freq; - snddma_android_size = dma.samples * ( sourceFormat.bitsPerSample >> 3 ); - dma.buffer = Z_Malloc( snddma_android_size * 2 ); - dma.samplepos = 0; - // dma.sampleframes = dma.samples / dma.format.channels; - dma.format.width = 2; - if( !dma.buffer ) return "malloc"; - - //snddma_android_mutex = trap_Mutex_Create(); - - dma.initialized = true; - - SNDDMA_Activate( true ); - - return NULL; -} - -qboolean SNDDMA_Init( void ) -{ - const char *initError; - - Msg( "OpenSL ES audio device initializing...\n" ); - - initError = SNDDMA_Android_Init(); - if( initError ) - { - Msg( S_ERROR "SNDDMA_Init: %s failed.\n", initError ); - SNDDMA_Shutdown(); - return false; - } - - Msg( "OpenSL ES audio initialized.\n" ); - dma.backendName = "OpenSL ES"; - return true; -} - -void SNDDMA_Shutdown( void ) -{ - Msg( "Closing OpenSL ES audio device...\n" ); - - if( snddma_android_player ) - { - (*snddma_android_player)->Destroy( snddma_android_player ); - snddma_android_player = NULL; - } - if( snddma_android_outputMix ) - { - (*snddma_android_outputMix)->Destroy( snddma_android_outputMix ); - snddma_android_outputMix = NULL; - } - if( snddma_android_engine ) - { - (*snddma_android_engine)->Destroy( snddma_android_engine ); - snddma_android_engine = NULL; - } - - if( dma.buffer ) - { - Z_Free( dma.buffer ); - dma.buffer = NULL; - } - - //if( snddma_android_mutex ) - //trap_Mutex_Destroy( &snddma_android_mutex ); - - Msg( "OpenSL ES audio device shut down.\n" ); -} - -void SNDDMA_Submit( void ) -{ - pthread_mutex_unlock( &snddma_android_mutex ); -} - -void SNDDMA_BeginPainting( void ) -{ - pthread_mutex_lock( &snddma_android_mutex ); -} - -qboolean VoiceCapture_Init( void ) -{ - return false; -} - -qboolean VoiceCapture_Activate( qboolean activate ) -{ - return false; -} - -qboolean VoiceCapture_Lock( qboolean lock ) -{ - return false; -} - -void VoiceCapture_Shutdown( void ) -{ - -} -#endif diff --git a/engine/platform/android/vid_android.c b/engine/platform/android/vid_android.c deleted file mode 100644 index 8b1492ec..00000000 --- a/engine/platform/android/vid_android.c +++ /dev/null @@ -1,665 +0,0 @@ -#include "platform/platform.h" -#include "input.h" -#include "client.h" -#include "filesystem.h" -#include "platform/android/android_priv.h" -#include "vid_common.h" -#include -#include -#include -#include - -static struct vid_android_s -{ - int gl_attribs[REF_GL_ATTRIBUTES_COUNT]; - qboolean gl_attribs_set[REF_GL_ATTRIBUTES_COUNT]; - EGLint gl_api; - qboolean gles1; - void *libgles1, *libgles2; - qboolean has_context; - ANativeWindow* window; -} vid_android; - -static struct nw_s -{ - void (*release)(ANativeWindow* window); - int32_t (*getWidth)(ANativeWindow* window); - int32_t (*getHeight)(ANativeWindow* window); - int32_t (*getFormat)(ANativeWindow* window); - int32_t (*setBuffersGeometry)(ANativeWindow* window, int32_t width, int32_t height, int32_t format); - int32_t (*lock)(ANativeWindow* window, ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds); - int32_t (*unlockAndPost)(ANativeWindow* window); - ANativeWindow* (*fromSurface)(JNIEnv* env, jobject surface); -} nw; - -#define NW_FF(x) {"ANativeWindow_"#x, (void*)&nw.x} - - -static dllfunc_t android_funcs[] = -{ - NW_FF(release), - NW_FF(getWidth), - NW_FF(getHeight), - NW_FF(getFormat), - NW_FF(setBuffersGeometry), - NW_FF(lock), - NW_FF(unlockAndPost), - NW_FF(fromSurface), - { NULL, NULL } -}; -#undef NW_FF -dll_info_t android_info = { "libandroid.so", android_funcs, false }; - -static struct egl_s -{ - EGLSurface (*GetCurrentSurface)(EGLint readdraw); - EGLDisplay (*GetCurrentDisplay)(void); - EGLint (*GetError)(void); - EGLBoolean (*SwapBuffers)(EGLDisplay dpy, EGLSurface surface); - EGLBoolean (*SwapInterval)(EGLDisplay dpy, EGLint interval); - void *(*GetProcAddress)(const char *procname); -} egl; -#undef GetProcAddress -#define EGL_FF(x) {"egl"#x, (void*)&egl.x} -static dllfunc_t egl_funcs[] = -{ - EGL_FF(SwapInterval), - EGL_FF(SwapBuffers), - EGL_FF(GetError), - EGL_FF(GetCurrentDisplay), - EGL_FF(GetCurrentSurface), - EGL_FF(GetProcAddress), - { NULL, NULL } -}; -#undef EGL_FF -dll_info_t egl_info = { "libEGL.so", egl_funcs, false }; - -static struct nativeegl_s -{ - qboolean valid; - void *window; - EGLDisplay dpy; - EGLSurface surface; - EGLContext context; - EGLConfig cfg; - EGLint numCfg; - - const char *extensions; -} negl; - -/* -======================== -Android_SwapInterval -======================== -*/ -static void Android_SwapInterval( int interval ) -{ - if( negl.valid ) - egl.SwapInterval( negl.dpy, interval ); -} - -/* -======================== -Android_SetTitle -======================== -*/ -static void Android_SetTitle( const char *title ) -{ - (*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.setTitle, (*jni.env)->NewStringUTF( jni.env, title ) ); -} - -/* -======================== -Android_SetIcon -======================== -*/ -static void Android_SetIcon( const char *path ) -{ - (*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.setIcon, (*jni.env)->NewStringUTF( jni.env, path ) ); -} - -/* -======================== -Android_GetScreenRes - -Resolution got from last resize event -======================== -*/ -static void Android_GetScreenRes( int *width, int *height ) -{ - *width=jni.width, *height=jni.height; -} - -/* -======================== -Android_SwapBuffers - -Update screen. Use native EGL if possible -======================== -*/ -void GL_SwapBuffers( void ) -{ - if( negl.valid ) - { - egl.SwapBuffers( negl.dpy, negl.surface ); - } - else - { - (*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.swapBuffers ); - } -} - -/* -======================== -Android_UpdateSurface - -Check if we may use native EGL without jni calls -======================== -*/ -void Android_UpdateSurface( qboolean active ) -{ - negl.valid = false; - - if( nw.release ) - { - if( vid_android.window && !active ) - { - nw.release( vid_android.window ); - vid_android.window = NULL; - } - - if( active ) - { - jobject surf; - if( vid_android.window ) - nw.release( vid_android.window ); - surf = (*jni.env)->CallStaticObjectMethod(jni.env, jni.actcls, jni.getSurface); - Con_Printf("s %p\n", surf); - vid_android.window = nw.fromSurface(jni.env, surf); - Con_Printf("w %p\n", vid_android.window); - nw.setBuffersGeometry(vid_android.window, 0, 0, WINDOW_FORMAT_RGB_565 ); - (*jni.env)->DeleteLocalRef( jni.env, surf ); - } - return; - } - - if( !vid_android.has_context ) - return; - - if( ( active && host.status == HOST_FRAME ) || !active ) - (*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.toggleEGL, 0 ); - - if( active ) - (*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.toggleEGL, 1 ); - - if( !Sys_CheckParm("-nativeegl") || !active ) - return; // enabled by user - - if( !egl.GetCurrentDisplay ) - return; - - negl.dpy = egl.GetCurrentDisplay(); - - if( negl.dpy == EGL_NO_DISPLAY ) - return; - - negl.surface = egl.GetCurrentSurface(EGL_DRAW); - - if( negl.surface == EGL_NO_SURFACE ) - return; - - // now check if swapBuffers does not give error - if( egl.SwapBuffers( negl.dpy, negl.surface ) == EGL_FALSE ) - return; - - // double check - if( egl.GetError() != EGL_SUCCESS ) - return; - - __android_log_print( ANDROID_LOG_VERBOSE, "Xash", "native EGL enabled" ); - - negl.valid = true; -} - -/* -======================== -Android_GetGLAttribute -======================== -*/ -static int Android_GetGLAttribute( int eglAttr ) -{ - int ret = (*jni.env)->CallStaticIntMethod( jni.env, jni.actcls, jni.getGLAttribute, eglAttr ); - // Con_Reportf( "Android_GetGLAttribute( %i ) => %i\n", eglAttr, ret ); - return ret; -} - -int Android_GetSelectedPixelFormat( void ) -{ - return (*jni.env)->CallStaticIntMethod( jni.env, jni.actcls, jni.getSelectedPixelFormat ); -} - -qboolean R_Init_Video( const int type ) -{ - char buf[MAX_VA_STRING]; - qboolean retval; - - switch( Android_GetSelectedPixelFormat() ) - { - case 1: - refState.desktopBitsPixel = 16; - break; - case 2: - refState.desktopBitsPixel = 8; - break; - default: - refState.desktopBitsPixel = 32; - break; - } - - if( FS_FileExists( GI->iconpath, true ) ) - { - Q_snprintf( buf, sizeof( buf ), "%s/%s/%s", COM_CheckStringEmpty( host.rodir ) ? host.rodir : host.rootdir, GI->gamefolder, GI->iconpath ); - Android_SetIcon( buf ); - } - - Android_SetTitle( GI->title ); - - VID_StartupGamma(); - - switch( type ) - { - case REF_SOFTWARE: - glw_state.software = true; - break; - case REF_GL: - glw_state.software = false; - Sys_LoadLibrary( &egl_info ); - - if( !glw_state.safe && Sys_GetParmFromCmdLine( "-safegl", buf ) ) - glw_state.safe = bound( SAFE_NO, Q_atoi( buf ), SAFE_DONTCARE ); - - break; - default: - Host_Error( "Can't initialize unknown context type %d!\n", type ); - break; - } - - if( glw_state.software ) - { - uint arg; -// Con_Reportf( S_ERROR "Native software mode isn't supported on Android yet! :(\n" ); -// return false; - Sys_LoadLibrary( &android_info ); - Android_UpdateSurface( true ); - if( !SW_CreateBuffer( jni.width, jni.height, &arg, &arg, &arg, &arg, &arg ) ) - return false; - } - - while( !(retval = VID_SetMode()) ) - { - glw_state.safe++; - if( glw_state.safe > SAFE_LAST ) - return false; - } - - switch( type ) - { - case REF_GL: - // refdll also can check extensions - ref.dllFuncs.GL_InitExtensions(); - break; - case REF_SOFTWARE: - default: - break; - } - - host.renderinfo_changed = false; - - return true; -} - -void R_Free_Video( void ) -{ - // (*jni.env)->CallStaticBooleanMethod( jni.env, jni.actcls, jni.deleteGLContext ); - - // VID_DestroyWindow (); - - // R_FreeVideoModes(); - Sys_FreeLibrary( &android_info ); - Sys_FreeLibrary( &egl_info ); - vid_android.has_context = false; - ref.dllFuncs.GL_ClearExtensions(); -} - -#define COPY_ATTR_IF_SET( refattr, attr ) \ - if( vid_android.gl_attribs_set[refattr] ) \ - { \ - attribs[i++] = attr; \ - attribs[i++] = vid_android.gl_attribs[refattr]; \ - } - -static size_t VID_GenerateConfig( EGLint *attribs, size_t size ) -{ - size_t i = 0; - - memset( attribs, 0, size * sizeof( EGLint ) ); - vid_android.gles1 = false; - memset( vid_android.gl_attribs, 0, sizeof( vid_android.gl_attribs )); - memset( vid_android.gl_attribs_set, 0, sizeof( vid_android.gl_attribs_set )); - - // refdll can request some attributes - ref.dllFuncs.GL_SetupAttributes( glw_state.safe ); - - COPY_ATTR_IF_SET( REF_GL_RED_SIZE, EGL_RED_SIZE ); - COPY_ATTR_IF_SET( REF_GL_GREEN_SIZE, EGL_GREEN_SIZE ); - COPY_ATTR_IF_SET( REF_GL_BLUE_SIZE, EGL_BLUE_SIZE ); - COPY_ATTR_IF_SET( REF_GL_ALPHA_SIZE, EGL_ALPHA_SIZE ); - COPY_ATTR_IF_SET( REF_GL_DEPTH_SIZE, EGL_DEPTH_SIZE ); - COPY_ATTR_IF_SET( REF_GL_STENCIL_SIZE, EGL_STENCIL_SIZE ); - COPY_ATTR_IF_SET( REF_GL_MULTISAMPLEBUFFERS, EGL_SAMPLE_BUFFERS ); - COPY_ATTR_IF_SET( REF_GL_MULTISAMPLESAMPLES, EGL_SAMPLES ); - - if( vid_android.gl_attribs_set[REF_GL_ACCELERATED_VISUAL] ) - { - attribs[i++] = EGL_CONFIG_CAVEAT; - attribs[i++] = vid_android.gl_attribs[REF_GL_ACCELERATED_VISUAL] ? EGL_NONE : EGL_DONT_CARE; - } - - // BigGL support - attribs[i++] = EGL_RENDERABLE_TYPE; - vid_android.gl_api = EGL_OPENGL_ES_API; - - if( vid_android.gl_attribs_set[REF_GL_CONTEXT_PROFILE_MASK] && - !( vid_android.gl_attribs[REF_GL_CONTEXT_PROFILE_MASK] & REF_GL_CONTEXT_PROFILE_ES )) - { - attribs[i++] = EGL_OPENGL_BIT; - vid_android.gl_api = EGL_OPENGL_API; - } - else if( vid_android.gl_attribs_set[REF_GL_CONTEXT_MAJOR_VERSION] && - vid_android.gl_attribs[REF_GL_CONTEXT_MAJOR_VERSION] >= 2 ) - { - attribs[i++] = EGL_OPENGL_ES2_BIT; - } - else - { - i--; // erase EGL_RENDERABLE_TYPE - vid_android.gles1 = true; - } - - attribs[i++] = EGL_NONE; - - return i; -} - -static size_t VID_GenerateContextConfig( EGLint *attribs, size_t size ) -{ - size_t i = 0; - - memset( attribs, 0, size * sizeof( EGLint )); - - /*if( Q_strcmp( negl.extensions, " EGL_KHR_create_context ") ) - { - if( vid_android.gl_attribs_set[REF_GL_CONTEXT_FLAGS] ) - { - attribs[i++] = 0x30FC; // EGL_CONTEXT_FLAGS_KHR - attribs[i++] = vid_android.gl_attribs[REF_GL_CONTEXT_FLAGS] & ((REF_GL_CONTEXT_ROBUST_ACCESS_FLAG << 1) - 1); - } - - if( vid_android.gl_attribs_set[REF_GL_CONTEXT_PROFILE_MASK] ) - { - int val = vid_android.gl_attribs[REF_GL_CONTEXT_PROFILE_MASK]; - - if( val & ( (REF_GL_CONTEXT_PROFILE_COMPATIBILITY << 1) - 1 ) ) - { - attribs[i++] = 0x30FD; // EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR; - attribs[i++] = val; - } - } - - COPY_ATTR_IF_SET( REF_GL_CONTEXT_MAJOR_VERSION, EGL_CONTEXT_CLIENT_VERSION ); - COPY_ATTR_IF_SET( REF_GL_CONTEXT_MINOR_VERSION, 0x30FB ); - } - else*/ - { - // without extension we can set only major version - COPY_ATTR_IF_SET( REF_GL_CONTEXT_MAJOR_VERSION, EGL_CONTEXT_CLIENT_VERSION ); - } - - attribs[i++] = EGL_NONE; - - return i; -} - -qboolean VID_SetMode( void ) -{ - EGLint format; - jintArray attribs, contextAttribs; - static EGLint nAttribs[32+1], nContextAttribs[32+1]; - const size_t attribsSize = ARRAYSIZE( nAttribs ); - size_t s1, s2; - - if( vid_android.has_context ) - { - R_ChangeDisplaySettings( 0, 0, false ); // width and height are ignored anyway - return true; - } - - s1 = VID_GenerateConfig(nAttribs, attribsSize); - s2 = VID_GenerateContextConfig(nContextAttribs, attribsSize); - - attribs = (*jni.env)->NewIntArray( jni.env, s1 ); - contextAttribs = (*jni.env)->NewIntArray( jni.env, s2 ); - - (*jni.env)->SetIntArrayRegion( jni.env, attribs, 0, s1, nAttribs ); - (*jni.env)->SetIntArrayRegion( jni.env, contextAttribs, 0, s2, nContextAttribs ); - - R_ChangeDisplaySettings( 0, 0, false ); // width and height are ignored anyway - - if( glw_state.software ) - return true; - - if( (*jni.env)->CallStaticBooleanMethod( jni.env, jni.actcls, jni.createGLContext, attribs, contextAttribs ) ) - { - vid_android.has_context = true; - return true; - } - - return false; -} - -rserr_t R_ChangeDisplaySettings( int width, int height, qboolean fullscreen ) -{ - int render_w, render_h; - uint rotate = vid_rotate->value; - - Android_GetScreenRes(&width, &height); - - render_w = width; - render_h = height; - - Con_Reportf( "R_ChangeDisplaySettings: forced resolution to %dx%d)\n", width, height); - - if( ref.dllFuncs.R_SetDisplayTransform( rotate, 0, 0, vid_scale->value, vid_scale->value ) ) - { - if( rotate & 1 ) - { - int swap = render_w; - - render_w = render_h; - render_h = swap; - } - - render_h /= vid_scale->value; - render_w /= vid_scale->value; - } - else - { - Con_Printf( S_WARN "failed to setup screen transform\n" ); - } - - R_SaveVideoMode( width, height, render_w, render_h ); - - refState.wideScreen = true; // V_AdjustFov will check for widescreen - - return rserr_ok; -} - -int GL_SetAttribute( int attr, int val ) -{ - if( attr < 0 || attr >= REF_GL_ATTRIBUTES_COUNT ) - return -1; - - vid_android.gl_attribs[attr] = val; - vid_android.gl_attribs_set[attr] = true; - return 0; -} - -int GL_GetAttribute( int attr, int *val ) -{ - EGLBoolean ret; - - if( attr < 0 || attr >= REF_GL_ATTRIBUTES_COUNT ) - return -1; - - if( !val ) - return -1; - - switch( attr ) - { - case REF_GL_RED_SIZE: - *val = Android_GetGLAttribute( EGL_RED_SIZE ); - return 0; - case REF_GL_GREEN_SIZE: - *val = Android_GetGLAttribute( EGL_GREEN_SIZE ); - return 0; - case REF_GL_BLUE_SIZE: - *val = Android_GetGLAttribute( EGL_BLUE_SIZE ); - return 0; - case REF_GL_ALPHA_SIZE: - *val = Android_GetGLAttribute( EGL_ALPHA_SIZE ); - return 0; - case REF_GL_DEPTH_SIZE: - *val = Android_GetGLAttribute( EGL_DEPTH_SIZE ); - return 0; - case REF_GL_STENCIL_SIZE: - *val = Android_GetGLAttribute( EGL_STENCIL_SIZE ); - return 0; - case REF_GL_MULTISAMPLESAMPLES: - *val = Android_GetGLAttribute( EGL_SAMPLES ); - return 0; - } - - return -1; -} - -int R_MaxVideoModes( void ) -{ - return 0; -} - -vidmode_t* R_GetVideoMode( int num ) -{ - return NULL; -} - -void* GL_GetProcAddress( const char *name ) // RenderAPI requirement -{ - void *gles; - void *addr; - - if( vid_android.gles1 ) - { - if( !vid_android.libgles1 ) - vid_android.libgles1 = dlopen("libGLESv1_CM.so", RTLD_NOW); - gles = vid_android.libgles1; - } - else - { - if( !vid_android.libgles2 ) - vid_android.libgles2 = dlopen("libGLESv2.so", RTLD_NOW); - gles = vid_android.libgles2; - } - - if( gles && ( addr = dlsym(gles, name ) ) ) - return addr; - - if( !egl.GetProcAddress ) - return NULL; - - return egl.GetProcAddress( name ); -} - -void GL_UpdateSwapInterval( void ) -{ - // disable VSync while level is loading - if( cls.state < ca_active ) - { - Android_SwapInterval( 0 ); - SetBits( gl_vsync->flags, FCVAR_CHANGED ); - } - else if( FBitSet( gl_vsync->flags, FCVAR_CHANGED )) - { - ClearBits( gl_vsync->flags, FCVAR_CHANGED ); - Android_SwapInterval( gl_vsync->value ); - } -} - -void *SW_LockBuffer( void ) -{ - ANativeWindow_Buffer buffer; - if( !nw.lock || !vid_android.window ) - return NULL; - if( nw.lock( vid_android.window, &buffer, NULL ) ) - return NULL; - if( buffer.width < refState.width || buffer.height < refState.height ) - return NULL; - return buffer.bits; -} - -void SW_UnlockBuffer( void ) -{ - if( nw.unlockAndPost ) - nw.unlockAndPost( vid_android.window ); -} - -qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b ) -{ - ANativeWindow_Buffer buffer; - int lock; - if( !nw.lock || !vid_android.window ) - return false; - nw.unlockAndPost( vid_android.window ); - - if( ( lock = nw.lock( vid_android.window, &buffer, NULL ) ) ) - { - Con_Printf( "SW_CreateBuffer: lock %d\n", lock ); - return false; - } - nw.unlockAndPost( vid_android.window ); - Con_Printf( "SW_CreateBuffer: buffer %d %d %x %d %p\n", buffer.width, buffer.height, buffer.format, buffer.stride, buffer.bits ); - if( width > buffer.width || height > buffer.height ) - { - Con_Printf( "SW_CreateBuffer: buffer too small %d %d\n", width, height ); - // resize event missed? - if( jni.width < buffer.width ) - jni.width = buffer.width; - if( jni.height < buffer.height ) - jni.width = buffer.height; - VID_SetMode(); - Android_UpdateSurface( 1 ); - return false; - } - if( buffer.format != WINDOW_FORMAT_RGB_565 ) - { - Con_Printf( "SW_CreateBuffer: wrong format %d\n", buffer.format ); - return false; - } - Con_Printf( "SW_CreateBuffer: ok\n" ); - *stride = buffer.stride; - - *bpp = 2; - *r = (((1 << 5) - 1) << (5+6)); - *g = (((1 << 6) - 1) << (5)); - *b = (((1 << 5) - 1) << (0)); - return true; -} diff --git a/engine/platform/platform.h b/engine/platform/platform.h index d65cb208..d54dab4f 100644 --- a/engine/platform/platform.h +++ b/engine/platform/platform.h @@ -47,9 +47,9 @@ void Android_SaveID( const char *id ); #if XASH_WIN32 void Platform_UpdateStatusLine( void ); -#else +#else static inline void Platform_UpdateStatusLine( void ) { } -#endif +#endif #if XASH_NSWITCH void NSwitch_Init( void ); @@ -108,11 +108,6 @@ void Platform_SetClipboardText( const char *buffer ); #define SDL_VERSION_ATLEAST( x, y, z ) 0 #endif -#if XASH_ANDROID -void Android_ShowMouse( qboolean show ); -void Android_MouseMove( float *x, float *y ); -#endif - /* ==============================================================================