SDL: fixed multithreaded video rendering crashing

This commit is contained in:
pelya
2016-08-14 23:51:11 +03:00
parent b4cbc0aa75
commit fe7c6be644
8 changed files with 44 additions and 33 deletions

View File

@@ -138,5 +138,4 @@ class Globals
public static boolean MultiThreadedVideo = false;
public static boolean OuyaEmulation = false; // For debugging
public static boolean RedirectStdout = false; // For debugging
}

View File

@@ -714,7 +714,7 @@ class DemoRenderer extends GLSurfaceView_SDL.Renderer
nativeInit( Globals.DataDir,
Globals.CommandLine,
( (Globals.SwVideoMode && Globals.MultiThreadedVideo) || Globals.CompatibilityHacksVideo ) ? 1 : 0,
Globals.RedirectStdout ? 1 : 0 );
0 );
System.exit(0); // The main() returns here - I don't bother with deinit stuff, just terminate process
}
@@ -958,7 +958,7 @@ class DemoRenderer extends GLSurfaceView_SDL.Renderer
}
private native void nativeInitJavaCallbacks();
private native void nativeInit(String CurrentPath, String CommandLine, int multiThreadedVideo, int isDebuggerConnected);
private native void nativeInit(String CurrentPath, String CommandLine, int multiThreadedVideo, int unused);
private native void nativeResize(int w, int h, int keepAspectRatio);
private native void nativeDone();
private native void nativeGlContextLost();

View File

@@ -79,7 +79,10 @@ extern DECLSPEC int SDLCALL SDL_ANDROID_SetAdvertisementPosition(int x, int y);
extern DECLSPEC int SDLCALL SDL_ANDROID_RequestNewAdvertisement(void);
/** Exports for Java environment and Video object instance */
/** Exports for Java environment and Video object instance.
To get JNIEnv pointer, use following code:
JNIEnv *env = NULL;
(*SDL_ANDROID_JavaVM())->GetEnv(SDL_ANDROID_JavaVM(), &env, JNI_VERSION_1_6); */
extern DECLSPEC JavaVM* SDL_ANDROID_JavaVM();
/*

View File

@@ -410,7 +410,7 @@ JNIEXPORT jint JNICALL JAVA_EXPORT_NAME(AudioThread_nativeAudioInitJavaCallbacks
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
{
jniVM = vm;
return JNI_VERSION_1_2;
return JNI_VERSION_1_6;
};
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved)

View File

@@ -1383,7 +1383,7 @@ int ANDROID_VideoInitMT(_THIS, SDL_PixelFormat *vformat)
SDL_Surface *ANDROID_SetVideoModeMT(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags)
{
if( flags & SDL_OPENGL || flags & SDL_HWSURFACE )
if( flags & SDL_OPENGL || (flags & SDL_HWSURFACE && !SDL_ANDROID_VideoForceSoftwareMode) )
{
return NULL;
}

View File

@@ -66,7 +66,6 @@ SDL_Rect SDL_ANDROID_ForceClearScreenRect[4] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
int SDL_ANDROID_ForceClearScreenRectAmount = 0;
// Extremely wicked JNI environment to call Java functions from C code
static JNIEnv* JavaEnv = NULL;
static jclass JavaRendererClass = NULL;
static jobject JavaRenderer = NULL;
static jmethodID JavaSwapBuffers = NULL;
@@ -114,14 +113,23 @@ static void appRestoredCallbackDefault(void)
SDL_ANDROID_ResumeAudioPlayback();
}
static SDL_ANDROID_ApplicationPutToBackgroundCallback_t appPutToBackgroundCallback = appPutToBackgroundCallbackDefault;
static SDL_ANDROID_ApplicationPutToBackgroundCallback_t appRestoredCallback = appRestoredCallbackDefault;
static SDL_ANDROID_ApplicationPutToBackgroundCallback_t openALPutToBackgroundCallback = NULL;
static SDL_ANDROID_ApplicationPutToBackgroundCallback_t openALRestoredCallback = NULL;
static inline JNIEnv *GetJavaEnv(void)
{
JavaVM *vm = SDL_ANDROID_JavaVM();
JNIEnv *ret = NULL;
(*vm)->GetEnv(vm, &ret, JNI_VERSION_1_6);
return ret;
}
int SDL_ANDROID_CallJavaSwapBuffers()
{
JNIEnv *JavaEnv = GetJavaEnv();
if( !glContextLost )
{
// Clear part of screen not used by SDL - on Android the screen contains garbage after each frame
@@ -236,12 +244,14 @@ JAVA_EXPORT_NAME(DemoRenderer_nativeGlContextRecreated) ( JNIEnv* env, jobject
int SDL_ANDROID_ToggleScreenKeyboardWithoutTextInput(void)
{
JNIEnv *JavaEnv = GetJavaEnv();
(*JavaEnv)->CallVoidMethod( JavaEnv, JavaRenderer, JavaToggleScreenKeyboardWithoutTextInput );
return 1;
}
int SDL_ANDROID_ToggleInternalScreenKeyboard(SDL_InternalKeyboard_t keyboard)
{
JNIEnv *JavaEnv = GetJavaEnv();
(*JavaEnv)->CallVoidMethod( JavaEnv, JavaRenderer, JavaToggleInternalScreenKeyboard, (jint)keyboard );
return 1;
}
@@ -254,6 +264,8 @@ extern SDL_Surface *SDL_GetVideoSurface(void);
void SDL_ANDROID_CallJavaShowScreenKeyboard(const char * oldText, char * outBuf, int outBufLen)
{
JNIEnv *JavaEnv = GetJavaEnv();
// Clear mouse button state, to avoid repeated clicks on the text field in some apps
SDL_ANDROID_MainThreadPushMouseButton( SDL_RELEASED, SDL_BUTTON_LEFT );
SDL_ANDROID_MainThreadPushMouseButton( SDL_RELEASED, SDL_BUTTON_RIGHT );
@@ -302,6 +314,7 @@ void SDL_ANDROID_CallJavaShowScreenKeyboard(const char * oldText, char * outBuf,
void SDL_ANDROID_CallJavaHideScreenKeyboard()
{
JNIEnv *JavaEnv = GetJavaEnv();
(*JavaEnv)->CallVoidMethod( JavaEnv, JavaRenderer, JavaHideScreenKeyboard );
}
@@ -318,6 +331,7 @@ JAVA_EXPORT_NAME(DemoGLSurfaceView_nativeScreenKeyboardShown) ( JNIEnv* env, jo
void SDL_ANDROID_CallJavaSetScreenKeyboardHintMessage(const char *hint)
{
JNIEnv *JavaEnv = GetJavaEnv();
(*JavaEnv)->PushLocalFrame(JavaEnv, 1);
jstring s = hint ? (*JavaEnv)->NewStringUTF(JavaEnv, hint) : NULL;
(*JavaEnv)->CallVoidMethod( JavaEnv, JavaRenderer, JavaSetScreenKeyboardHintMessage, s );
@@ -328,13 +342,14 @@ void SDL_ANDROID_CallJavaSetScreenKeyboardHintMessage(const char *hint)
void SDL_ANDROID_CallJavaStartAccelerometerGyroscope(int start)
{
JNIEnv *JavaEnv = GetJavaEnv();
(*JavaEnv)->CallVoidMethod( JavaEnv, JavaRenderer, JavaStartAccelerometerGyroscope, (jint) start );
}
JNIEXPORT void JNICALL
JAVA_EXPORT_NAME(DemoRenderer_nativeInitJavaCallbacks) ( JNIEnv* env, jobject thiz )
{
JavaEnv = env;
JNIEnv *JavaEnv = env;
JavaRenderer = (*JavaEnv)->NewGlobalRef( JavaEnv, thiz );
JavaRendererClass = (*JavaEnv)->GetObjectClass(JavaEnv, thiz);
@@ -433,6 +448,7 @@ void SDLCALL SDL_ANDROID_GetClipboardText(char * buf, int len)
int SDLCALL SDL_SetClipboardText(const char *text)
{
JNIEnv *JavaEnv = GetJavaEnv();
(*JavaEnv)->PushLocalFrame(JavaEnv, 1);
jstring s = (*JavaEnv)->NewStringUTF(JavaEnv, text);
(*JavaEnv)->CallVoidMethod( JavaEnv, JavaRenderer, JavaSetClipboardText, s );
@@ -444,6 +460,7 @@ int SDLCALL SDL_SetClipboardText(const char *text)
char * SDLCALL SDL_GetClipboardText(void)
{
char *buf = NULL;
JNIEnv *JavaEnv = GetJavaEnv();
(*JavaEnv)->PushLocalFrame( JavaEnv, 1 );
jstring s = (jstring) (*JavaEnv)->CallObjectMethod( JavaEnv, JavaRenderer, JavaGetClipboardText );
if( s )
@@ -489,6 +506,7 @@ JAVA_EXPORT_NAME(DemoRenderer_nativeClipboardChanged) ( JNIEnv* env, jobject thi
int SDLCALL SDL_ANDROID_GetAdvertisementParams(int * visible, SDL_Rect * position)
{
jint arr[5];
JNIEnv *JavaEnv = GetJavaEnv();
(*JavaEnv)->PushLocalFrame( JavaEnv, 1 );
jintArray elemArr = (*JavaEnv)->NewIntArray(JavaEnv, 5);
if (elemArr == NULL)
@@ -511,16 +529,19 @@ int SDLCALL SDL_ANDROID_GetAdvertisementParams(int * visible, SDL_Rect * positio
}
int SDLCALL SDL_ANDROID_SetAdvertisementVisible(int visible)
{
JNIEnv *JavaEnv = GetJavaEnv();
(*JavaEnv)->CallVoidMethod( JavaEnv, JavaRenderer, JavaSetAdvertisementVisible, (jint)visible );
return 1;
}
int SDLCALL SDL_ANDROID_SetAdvertisementPosition(int left, int top)
{
JNIEnv *JavaEnv = GetJavaEnv();
(*JavaEnv)->CallVoidMethod( JavaEnv, JavaRenderer, JavaSetAdvertisementPosition, (jint)left, (jint)top );
return 1;
}
int SDLCALL SDL_ANDROID_RequestNewAdvertisement(void)
{
JNIEnv *JavaEnv = GetJavaEnv();
(*JavaEnv)->CallVoidMethod( JavaEnv, JavaRenderer, JavaRequestNewAdvertisement );
return 1;
}
@@ -528,6 +549,7 @@ int SDLCALL SDL_ANDROID_RequestNewAdvertisement(void)
int SDLCALL SDL_ANDROID_CloudSave(const char *filename, const char *saveId, const char *dialogTitle,
const char *description, const char *screenshotFile, uint64_t playedTimeMs)
{
JNIEnv *JavaEnv = GetJavaEnv();
__android_log_print(ANDROID_LOG_INFO, "libSDL", "SDL_ANDROID_CloudSave: played time %llu", playedTimeMs);
if( !filename )
return 0;
@@ -557,6 +579,7 @@ int SDLCALL SDL_ANDROID_CloudSave(const char *filename, const char *saveId, cons
int SDLCALL SDL_ANDROID_CloudLoad(const char *filename, const char *saveId, const char *dialogTitle)
{
JNIEnv *JavaEnv = GetJavaEnv();
if( !filename )
return 0;
if( !saveId )
@@ -577,6 +600,7 @@ int SDLCALL SDL_ANDROID_CloudLoad(const char *filename, const char *saveId, cons
void SDLCALL SDL_ANDROID_OpenExternalApp(const char *package, const char *activity, const char *data)
{
JNIEnv *JavaEnv = GetJavaEnv();
(*JavaEnv)->PushLocalFrame(JavaEnv, 3);
jstring s1 = package ? (*JavaEnv)->NewStringUTF(JavaEnv, package) : (*JavaEnv)->NewStringUTF(JavaEnv, "");
jstring s2 = activity ? (*JavaEnv)->NewStringUTF(JavaEnv, activity) : (*JavaEnv)->NewStringUTF(JavaEnv, "");
@@ -590,6 +614,7 @@ void SDLCALL SDL_ANDROID_OpenExternalApp(const char *package, const char *activi
void SDLCALL SDL_ANDROID_RestartMyself(const char *restartParams)
{
JNIEnv *JavaEnv = GetJavaEnv();
(*JavaEnv)->PushLocalFrame(JavaEnv, 1);
jstring s1 = restartParams ? (*JavaEnv)->NewStringUTF(JavaEnv, restartParams) : (*JavaEnv)->NewStringUTF(JavaEnv, "");
(*JavaEnv)->CallVoidMethod( JavaEnv, JavaRenderer, JavaRequestRestartMyself, s1 );
@@ -599,6 +624,7 @@ void SDLCALL SDL_ANDROID_RestartMyself(const char *restartParams)
void SDLCALL SDL_ANDROID_SetConfigOption(int option, int value)
{
JNIEnv *JavaEnv = GetJavaEnv();
(*JavaEnv)->CallVoidMethod( JavaEnv, JavaRenderer, JavaRequestSetConfigOption, (jint)option, (jint)value );
}

View File

@@ -18,7 +18,7 @@ extern "C" void SDL_Android_Init(JNIEnv* env, jclass cls);
// Library init
extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
return JNI_VERSION_1_4;
return JNI_VERSION_1_6;
}
// Start up the SDL app

View File

@@ -44,26 +44,17 @@ jobject SDL_ANDROID_JniVideoObject()
return static_thiz;
}
void redirectStdout()
{
freopen( "stdout.log", "w", stdout );
dup2( fileno(stdout), fileno(stderr) );
}
#if SDL_VERSION_ATLEAST(1,3,0)
#else
extern void SDL_ANDROID_MultiThreadedVideoLoopInit();
extern void SDL_ANDROID_MultiThreadedVideoLoop();
static int threadedMain(void * waitForDebugger);
static int threadedMain(void * unused);
int threadedMain(void * waitForDebugger)
int threadedMain(void * unused)
{
if( waitForDebugger )
{
//__android_log_print(ANDROID_LOG_INFO, "libSDL", "We are being debugged - waiting for debugger for 7 seconds");
//usleep(7000000);
}
static JNIEnv *JavaEnv = NULL;
(*SDL_ANDROID_JavaVM())->AttachCurrentThread(SDL_ANDROID_JavaVM(), &JavaEnv, NULL);
SDL_main( argc, argv );
__android_log_print(ANDROID_LOG_INFO, "libSDL", "Application closed, calling exit(0)");
exit(0);
@@ -71,7 +62,7 @@ int threadedMain(void * waitForDebugger)
#endif
extern C_LINKAGE void
JAVA_EXPORT_NAME(DemoRenderer_nativeInit) ( JNIEnv* env, jobject thiz, jstring jcurdir, jstring cmdline, jint multiThreadedVideo, jint waitForDebugger )
JAVA_EXPORT_NAME(DemoRenderer_nativeInit) ( JNIEnv* env, jobject thiz, jstring jcurdir, jstring cmdline, jint multiThreadedVideo, jint unused )
{
int i = 0;
char curdir[PATH_MAX] = "";
@@ -93,9 +84,6 @@ JAVA_EXPORT_NAME(DemoRenderer_nativeInit) ( JNIEnv* env, jobject thiz, jstring
setenv("HOME", curdir, 1);
__android_log_print(ANDROID_LOG_INFO, "libSDL", "Changing curdir to \"%s\"", curdir);
if( waitForDebugger )
redirectStdout();
jstr = (*env)->GetStringUTFChars(env, cmdline, NULL);
if (jstr != NULL && strlen(jstr) > 0)
@@ -147,17 +135,12 @@ JAVA_EXPORT_NAME(DemoRenderer_nativeInit) ( JNIEnv* env, jobject thiz, jstring
#else
if( ! multiThreadedVideo )
{
if( waitForDebugger )
{
//__android_log_print(ANDROID_LOG_INFO, "libSDL", "We are being debugged - waiting for debugger for 7 seconds");
//usleep(7000000);
}
SDL_main( argc, argv );
}
else
{
SDL_ANDROID_MultiThreadedVideoLoopInit();
SDL_CreateThread(threadedMain, (void *)waitForDebugger);
SDL_CreateThread(threadedMain, NULL);
SDL_ANDROID_MultiThreadedVideoLoop();
}
#endif