Index: src/audio/android/SDL_androidaudio.c =================================================================== --- src/audio/android/SDL_androidaudio.c (revision 9231) +++ src/audio/android/SDL_androidaudio.c (working copy) @@ -133,7 +133,7 @@ // Extremely wicked JNI environment to call Java functions from C code static jbyteArray audioBufferJNI = NULL; -static JavaVM *jniVM = NULL; +JavaVM *jniVM = NULL; static jobject JavaAudioThread = NULL; static jmethodID JavaInitAudio = NULL; static jmethodID JavaDeinitAudio = NULL; Index: src/video/android/SDL_androidvideo-1.2.c =================================================================== --- src/video/android/SDL_androidvideo-1.2.c (revision 9231) +++ src/video/android/SDL_androidvideo-1.2.c (working copy) @@ -227,6 +227,10 @@ SDL_modelist[SDL_NUMMODES] = NULL; SDL_VideoInit_1_3(NULL, 0); + // Set to 1 to allow first SemWait to pass in FlipHWSurface +#ifdef SDL_ANDROID_USE_2BUFS + swap_sem = SDL_CreateSemaphore(1); +#endif /* We're done! */ return(0); @@ -239,6 +243,10 @@ return SDL_modelist; } +SDL_Texture *texture[2] = { NULL, }; +void *pix[2] = { NULL, }; +static int cur_pix = 0; + SDL_Surface *ANDROID_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags) { @@ -282,20 +290,35 @@ current->hwdata = NULL; if( ! (flags & SDL_HWSURFACE) ) { - current->pixels = SDL_malloc(width * height * ANDROID_BYTESPERPIXEL); - if ( ! current->pixels ) { - __android_log_print(ANDROID_LOG_INFO, "libSDL", "Couldn't allocate buffer for requested mode"); - SDL_SetError("Couldn't allocate buffer for requested mode"); - return(NULL); + int i; +#if SDL_ANDROID_USE_2BUFS + int num = 1; +#else + int num = 2; +#endif + for (i=0; ipixels = NULL; + SDL_OutOfMemory(); + return(NULL); + } } - SDL_memset(current->pixels, 0, width * height * ANDROID_BYTESPERPIXEL); - current->hwdata = (struct private_hwdata *)SDL_CreateTexture(SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STATIC, width, height); - if( !current->hwdata ) { - SDL_free(current->pixels); - current->pixels = NULL; - SDL_OutOfMemory(); - return(NULL); - } + cur_pix = 0; + current->pixels = pix[cur_pix]; + //SDL_SetTextureScaleMode(tex, SDL_TEXTURESCALEMODE_NONE); + //SDL_SetTextureBlendMode(tex, SDL_BLENDMODE_NONE); + //SDL_SetTextureAlphaMod(tex, SDL_TEXTUREMODULATE_NONE); + current->hwdata = (struct private_hwdata *)texture[cur_pix]; // Register main video texture to be recreated when needed HwSurfaceCount++; HwSurfaceList = SDL_realloc( HwSurfaceList, HwSurfaceCount * sizeof(SDL_Surface *) ); @@ -330,6 +353,7 @@ */ void ANDROID_VideoQuit(_THIS) { + int i; if( ! sdl_opengl ) { HwSurfaceCount = 0; @@ -337,10 +361,15 @@ SDL_free(HwSurfaceList); HwSurfaceList = NULL; - if( SDL_CurrentVideoSurface->hwdata ) - SDL_DestroyTexture((struct SDL_Texture *)SDL_CurrentVideoSurface->hwdata); - if( SDL_CurrentVideoSurface->pixels ) - SDL_free(SDL_CurrentVideoSurface->pixels); + for (i=0; i<2; i++) { + if( texture[i] ) + SDL_DestroyTexture(texture[i]); + if( pix[i] ) + SDL_free(pix[i]); + pix[i] = NULL; + texture[i] = NULL; + } + SDL_CurrentVideoSurface->pixels = NULL; SDL_CurrentVideoSurface = NULL; SDL_DestroyWindow(SDL_VideoWindow); @@ -349,9 +378,10 @@ SDL_ANDROID_sFakeWindowWidth = 0; SDL_ANDROID_sFakeWindowWidth = 0; +#ifdef SDL_ANDROID_USE_2BUFS + SDL_DestroySemaphore(swap_sem); +#endif - int i; - /* Free video mode lists */ for ( i=0; ihwdata && SDL_CurrentVideoSurface->pixels ) { SDL_Rect rect; +#if SDL_ANDROID_USE_2BUFS + if (cur_pix) __android_log_print(ANDROID_LOG_INFO, "libSDL", "ANDROID_FlipHWSurface() 1"); + else __android_log_print(ANDROID_LOG_INFO, "libSDL", "ANDROID_FlipHWSurface() 0"); +#endif rect.x = 0; rect.y = 0; rect.w = SDL_CurrentVideoSurface->w; rect.h = SDL_CurrentVideoSurface->h; - SDL_UpdateTexture((struct SDL_Texture *)SDL_CurrentVideoSurface->hwdata, &rect, SDL_CurrentVideoSurface->pixels, SDL_CurrentVideoSurface->pitch); - SDL_RenderCopy((struct SDL_Texture *)SDL_CurrentVideoSurface->hwdata, &rect, &rect); - } +#if SDL_ANDROID_USE_2BUFS + SDL_SemWait(swap_sem); // Not performing this until previous swap is finished +#endif + SDL_UpdateTexture(texture[cur_pix], &rect, pix[cur_pix], SDL_CurrentVideoSurface->pitch); + SDL_RenderCopy(texture[cur_pix], &rect, &rect); + SDL_ANDROID_CallJavaSwapBuffers(); +#if SDL_ANDROID_USE_2BUFS + cur_pix ^= 1; + SDL_CurrentVideoSurface->pixels = pix[cur_pix]; + SDL_CurrentVideoSurface->hwdata = (struct private_hwdata *)texture[cur_pix]; +#endif + } else + SDL_ANDROID_CallJavaSwapBuffers(); - SDL_ANDROID_CallJavaSwapBuffers(); - return(0); }; Index: src/video/android/SDL_androidvideo.c =================================================================== --- src/video/android/SDL_androidvideo.c (revision 9231) +++ src/video/android/SDL_androidvideo.c (working copy) @@ -49,6 +49,10 @@ // The device screen dimensions to draw on int SDL_ANDROID_sWindowWidth = 0; int SDL_ANDROID_sWindowHeight = 0; +#ifdef SDL_ANDROID_USE_2BUFS +SDL_sem *swap_sem = NULL; +SDL_Thread *swap_thread = NULL; +#endif // Extremely wicked JNI environment to call Java functions from C code static JNIEnv* JavaEnv = NULL; @@ -56,7 +60,24 @@ static jobject JavaRenderer = NULL; static jmethodID JavaSwapBuffers = NULL; static int glContextLost = 0; +extern JavaVM *jniVM; +#ifdef SDL_ANDROID_USE_2BUFS +// Should ideally loop endlessly, waiting on a semaphore, +// CallIntMethod return stored to a static value, and a loop end bool +// to properly finish the function +int ThreadSwap(void *data) +{ + __android_log_print(ANDROID_LOG_INFO, "libSDL", "doing the swap"); + //(*jniVM)->AttachCurrentThread(jniVM, &JavaEnv, NULL); + int ret = (*JavaEnv)->CallIntMethod( JavaEnv, JavaRenderer, JavaSwapBuffers ); + //(*jniVM)->DetachCurrentThread(jniVM); + __android_log_print(ANDROID_LOG_INFO, "libSDL", "swapped"); + SDL_SemPost(swap_sem); // Can be called again + return ret; +} +#endif + static void appPutToBackgroundCallbackDefault(void) { SDL_ANDROID_PauseAudioPlayback(); @@ -75,8 +96,22 @@ { SDL_ANDROID_processAndroidTrackballDampening(); } +#ifdef SDL_ANDROID_USE_2BUFS + if (swap_thread) { + int ret; + __android_log_print(ANDROID_LOG_INFO, "libSDL", "doing the wait"); + // Because of the semaphore this is useless, but this is done to get return value + SDL_WaitThread(swap_thread, &ret); + swap_thread = NULL; + if (!ret) + return 0; + __android_log_print(ANDROID_LOG_INFO, "libSDL", "done waiting"); + } + swap_thread = SDL_CreateThread(ThreadSwap, NULL); +#else if( ! (*JavaEnv)->CallIntMethod( JavaEnv, JavaRenderer, JavaSwapBuffers ) ) return 0; +#endif if( glContextLost ) { glContextLost = 0; Index: src/video/android/SDL_androidvideo.h =================================================================== --- src/video/android/SDL_androidvideo.h (revision 9231) +++ src/video/android/SDL_androidvideo.h (working copy) @@ -22,8 +22,14 @@ #ifndef _SDL_androidvideo_h #define _SDL_androidvideo_h +#define SDL_ANDROID_USE_2BUFS + #include "SDL_config.h" #include "SDL_video.h" +#ifdef SDL_ANDROID_USE_2BUFS +# include "SDL_thread.h" +# include "SDL_mutex.h" +#endif extern void ANDROID_InitOSKeymap(); @@ -36,6 +42,9 @@ extern void SDL_ANDROID_VideoContextRecreated(); extern void SDL_ANDROID_processAndroidTrackballDampening(); extern SDL_VideoDevice *ANDROID_CreateDevice_1_3(int devindex); +#ifdef SDL_ANDROID_USE_2BUFS +extern SDL_sem *swap_sem; +extern SDL_Thread *swap_thread; +#endif - #endif /* _SDL_androidvideo_h */