From 877d51d2452bf70933ea6f5b52b4075aad1ec6c7 Mon Sep 17 00:00:00 2001 From: Paul Hunkin Date: Tue, 29 Jun 2010 00:40:12 +1200 Subject: [PATCH] - Restructured threads and application structure. - Moved to SurfaceView instead of GLSurfaceView - Moved to C++ for the android library --- android/testproject/jni/Android.mk | 4 +- android/testproject/jni/app-android.c | 183 ------------------ android/testproject/jni/app-android.cpp | 101 ++++++++++ .../jni/{importgl.c => importgl.cpp} | 0 .../src/org/libsdl/android/TestActivity.java | 173 +++++++++++++++-- src/video/android/SDL_androidgl.c | 14 +- 6 files changed, 258 insertions(+), 217 deletions(-) delete mode 100644 android/testproject/jni/app-android.c create mode 100644 android/testproject/jni/app-android.cpp rename android/testproject/jni/{importgl.c => importgl.cpp} (100%) diff --git a/android/testproject/jni/Android.mk b/android/testproject/jni/Android.mk index 3f3f20250..7d3e649da 100644 --- a/android/testproject/jni/Android.mk +++ b/android/testproject/jni/Android.mk @@ -11,8 +11,8 @@ LOCAL_CFLAGS := -DANDROID_NDK \ -I$(SDL)/include LOCAL_SRC_FILES := \ - importgl.c \ - app-android.c \ + importgl.cpp \ + app-android.cpp \ lesson05.c \ LOCAL_LDLIBS := -lGLESv1_CM -ldl -llog -lSDL -lEGL -lgcc -L$(SDL) -L$(SDL)/build-scripts/android_libs/ diff --git a/android/testproject/jni/app-android.c b/android/testproject/jni/app-android.c deleted file mode 100644 index 6d458a99e..000000000 --- a/android/testproject/jni/app-android.c +++ /dev/null @@ -1,183 +0,0 @@ -/******************************************************************************* - Headers -*******************************************************************************/ -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include "importgl.h" -#include "egl.h" - -/******************************************************************************* - Globals -*******************************************************************************/ -int gAppAlive = 1; - -static int sWindowWidth = 320; -static int sWindowHeight = 480; -static int sDemoStopped = 0; - -static long _getTime(void){ - struct timeval now; - gettimeofday(&now, NULL); - return (long)(now.tv_sec*1000 + now.tv_usec/1000); -} - - -/******************************************************************************* - Things used by libsdl -*******************************************************************************/ -pthread_mutex_t mSDLRenderMutex; -pthread_cond_t mSDLRenderCondition; - -EGLContext mContext; -EGLDisplay mDisplay; -EGLSurface mRead; -EGLSurface mDraw; - -/******************************************************************************* - SDL thread -*******************************************************************************/ -pthread_t mSDLThread = 0; - -void* sdlThreadProc(void* args){ - __android_log_print(ANDROID_LOG_INFO, "SDL", "Thread Entry"); - - if(!eglMakeCurrent(mDisplay, mDraw, mRead, mContext)){ - __android_log_print(ANDROID_LOG_INFO, "SDL", "Couldn't make current: 0x%x", eglGetError()); - return NULL; - } - - - return (void *)SDL_main(); -} - -/******************************************************************************* - Initialize the graphics state -*******************************************************************************/ -void Java_org_libsdl_android_TestRenderer_nativeInit( JNIEnv* env ) -{ - importGLInit(); - - gAppAlive = 1; - sDemoStopped = 0; - - __android_log_print(ANDROID_LOG_INFO, "SDL", "Entry point"); - - pthread_mutex_init(&mSDLRenderMutex, NULL); - pthread_cond_init (&mSDLRenderCondition, NULL); - - //Get some egl stuff we need - mContext = eglGetCurrentContext(); - mDisplay = eglGetCurrentDisplay(); - mRead = eglGetCurrentSurface(EGL_READ); - mDraw = eglGetCurrentSurface(EGL_DRAW); - - //We need to abandon our context so SDL can have it - if(!eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)){ - __android_log_print(ANDROID_LOG_INFO, "SDL", "Couldn't abandon context: 0x%x", eglGetError()); - return NULL; - } - - //Spin up the SDL thread - int r = pthread_create(&mSDLThread, NULL, sdlThreadProc, NULL); - - if(r != 0){ - __android_log_print(ANDROID_LOG_INFO, "SDL", "Couldn't spawn thread: %d", r); - }else{ - __android_log_print(ANDROID_LOG_INFO, "SDL", "Started SDL thread"); - } - -} - -/******************************************************************************* - Resize -*******************************************************************************/ -void Java_org_libsdl_android_TestRenderer_nativeResize( JNIEnv* env, - jobject thiz, - jint w, - jint h ) -{ - sWindowWidth = w; - sWindowHeight = h; - __android_log_print(ANDROID_LOG_INFO, "SDL", "resize w=%d h=%d", w, h); - -} - -/******************************************************************************* - Finalize (ie: shutdown) -*******************************************************************************/ -void Java_org_libsdl_android_TestRenderer_nativeDone( JNIEnv* env ) -{ - - //shut down the app - - importGLDeinit(); - - __android_log_print(ANDROID_LOG_INFO, "SDL", "Finalize"); -} - -/******************************************************************************* - Pause (ie: stop as soon as possible) -*******************************************************************************/ -void Java_org_libsdl_android_TestGLSurfaceView_nativePause( JNIEnv* env ) -{ - sDemoStopped = !sDemoStopped; - if (sDemoStopped) { - //we paused - __android_log_print(ANDROID_LOG_INFO, "SDL", "Pause"); - } else { - //we resumed - __android_log_print(ANDROID_LOG_INFO, "SDL", "Resume"); - } -} - -/******************************************************************************* - Render the next frame -*******************************************************************************/ - -volatile int frames = 0; -volatile int startSDL = 0; - -//eglSwapBuffers(mDisplay, mDraw); - -void Java_org_libsdl_android_TestRenderer_nativeRender( JNIEnv* env ) -{ - __android_log_print(ANDROID_LOG_INFO, "SDL", "JNI: BeginRender"); - - //Let the SDL thread do an entire run - int lastFrames = frames; - startSDL = 1; - - //wait for it to finish - while(lastFrames == frames){ - ; - } - - __android_log_print(ANDROID_LOG_INFO, "SDL", "JNI: EndRender"); -} - -void sdl_render(){ - - //When we get here, we've accumulated a full frame - - __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: BeginRender"); - - frames++; - - while(startSDL == 0){ - ; - } - startSDL = 0; - - __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: EndRender"); -} - diff --git a/android/testproject/jni/app-android.cpp b/android/testproject/jni/app-android.cpp new file mode 100644 index 000000000..bcd1fcf88 --- /dev/null +++ b/android/testproject/jni/app-android.cpp @@ -0,0 +1,101 @@ +/******************************************************************************* + Headers +*******************************************************************************/ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "importgl.h" +#include "egl.h" + +/******************************************************************************* + Globals +*******************************************************************************/ +static long _getTime(void){ + struct timeval now; + gettimeofday(&now, NULL); + return (long)(now.tv_sec*1000 + now.tv_usec/1000); +} + +JNIEnv* mEnv = NULL; +JavaVM* mVM = NULL; + +//Main activity +jclass mActivityInstance; + +//method signatures +jmethodID midCreateGLContext; +jmethodID midFlipBuffers; + +extern "C" int SDL_main(); + +/******************************************************************************* + Functions called by JNI +*******************************************************************************/ + +extern "C" void Java_org_libsdl_android_TestActivity_nativeInit( JNIEnv* env, jobject obj ) +{ + __android_log_print(ANDROID_LOG_INFO, "SDL", "JNI: NativeInit"); + + mEnv = env; + + SDL_main(); +} + +extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) +{ + JNIEnv* env = NULL; + jint result = -1; + + if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { + return result; + } + + mEnv = env; + + __android_log_print(ANDROID_LOG_INFO, "SDL", "JNI: OnLoad"); + + jclass cls = mEnv->FindClass ("org/libsdl/android/TestActivity"); + mActivityInstance = cls; + midCreateGLContext = mEnv->GetStaticMethodID(cls,"createGLContext","()V"); + midFlipBuffers = mEnv->GetStaticMethodID(cls,"flipBuffers","()V"); + + if(!midCreateGLContext || !midFlipBuffers){ + __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: Bad mids\n"); + }else{ + __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: Good mids\n"); + } + + return JNI_VERSION_1_4; +} + + + +/******************************************************************************* + Functions called by SDL +*******************************************************************************/ +extern "C" void sdl_create_context(){ + __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: sdl_create_context()\n"); + + mEnv->CallStaticVoidMethod(mActivityInstance, midCreateGLContext ); + __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: sdl_create_context() return\n"); + + // exit(1); +} + +extern "C" void sdl_render(){ + + //When we get here, we've accumulated a full frame + //__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: sdl_render()"); + + mEnv->CallStaticVoidMethod(mActivityInstance, midFlipBuffers ); +} + diff --git a/android/testproject/jni/importgl.c b/android/testproject/jni/importgl.cpp similarity index 100% rename from android/testproject/jni/importgl.c rename to android/testproject/jni/importgl.cpp diff --git a/android/testproject/src/org/libsdl/android/TestActivity.java b/android/testproject/src/org/libsdl/android/TestActivity.java index 9581f9ea2..f022662e4 100644 --- a/android/testproject/src/org/libsdl/android/TestActivity.java +++ b/android/testproject/src/org/libsdl/android/TestActivity.java @@ -2,66 +2,197 @@ import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; +import javax.microedition.khronos.egl.*; import android.app.Activity; import android.content.Context; -import android.opengl.GLSurfaceView; +import android.view.SurfaceHolder; +import android.view.SurfaceView; import android.os.Bundle; import android.view.MotionEvent; +import android.util.Log; +import android.graphics.*; + +import java.lang.*; + + +//http://www.mail-archive.com/android-beginners@googlegroups.com/msg01830.html + +/* +In TestActivity::onResume() call SDL_Init +SDL_GL_CreateContext call SDLSurface::createSDLGLContext() +SDL_GL_FlipBuffers calls SDLSurface::flip() + +*/ + + public class TestActivity extends Activity { - @Override + protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mGLView = new TestGLSurfaceView(this); - setContentView(mGLView); + mSurface = new SDLSurface(getApplication()); + setContentView(mSurface); + SurfaceHolder holder = mSurface.getHolder(); + holder.setType(SurfaceHolder.SURFACE_TYPE_GPU); } - @Override protected void onPause() { super.onPause(); - mGLView.onPause(); } - @Override protected void onResume() { super.onResume(); - mGLView.onResume(); + + //All set up. Start up SDL + + } - private GLSurfaceView mGLView; + private static SDLSurface mSurface; static { System.loadLibrary("sanangeles"); } + + //C functions we call + public static native void nativeInit(); + + + //Java functions called from C + private static void createGLContext(){ + mSurface.initEGL(); + } + + public static void flipBuffers(){ + mSurface.flipBuffers(); + } } -class TestGLSurfaceView extends GLSurfaceView { - public TestGLSurfaceView(Context context) { - super(context); - mRenderer = new TestRenderer(); - setRenderer(mRenderer); +class SDLThread implements Runnable{ + public void run(){ + TestActivity.nativeInit(); + } +} + +class SDLSurface extends SurfaceView implements SurfaceHolder.Callback{ + + private EGLContext mEGLContext; + private EGLSurface mEGLSurface; + private EGLDisplay mEGLDisplay; + + public void surfaceCreated(SurfaceHolder holder) { + Log.v("SDL","Surface created"); - //setRenderMode(RENDERMODE_WHEN_DIRTY); + Thread runner = new Thread(new SDLThread(), "SDLThread"); // (1) Create a new thread. + runner.start(); // (2) Start the thread + } - public boolean onTouchEvent(final MotionEvent event) { - if (event.getAction() == MotionEvent.ACTION_DOWN) { - nativePause(); + public void surfaceDestroyed(SurfaceHolder holder) { + Log.v("SDL","Surface destroyed"); + } + + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + + } + + + boolean initEGL(){ + Log.v("SDL","Starting up"); + + try{ + + // Get an EGL instance + EGL10 egl = (EGL10)EGLContext.getEGL(); + + // Get to the default display. + EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); + + // We can now initialize EGL for that display + int[] version = new int[2]; + egl.eglInitialize(dpy, version); + + // Specify a configuration for our opengl session + // and grab the first configuration that matches is + int[] configSpec = { + //EGL10.EGL_DEPTH_SIZE, 16, + EGL10.EGL_NONE + }; + EGLConfig[] configs = new EGLConfig[1]; + int[] num_config = new int[1]; + egl.eglChooseConfig(dpy, configSpec, configs, 1, num_config); + EGLConfig config = configs[0]; + + // Create an OpenGL ES context. This must be done only once + EGLContext ctx = egl.eglCreateContext(dpy, config, EGL10.EGL_NO_CONTEXT, null); + + // Create an EGL surface we can render into. + EGLSurface surface = egl.eglCreateWindowSurface(dpy, config, this, null); + + // Before we can issue GL commands, we need to make sure + // the context is current and bound to a surface. + egl.eglMakeCurrent(dpy, surface, surface, ctx); + + mEGLContext = ctx; + mEGLDisplay = dpy; + mEGLSurface = surface; + }catch(Exception e){ + Log.v("SDL", e + ""); } + + Log.v("SDL","Done making!"); + return true; } - TestRenderer mRenderer; + public SDLSurface(Context context) { + super(context); + + getHolder().addCallback(this); + + } + + public void onDraw(Canvas canvas) { + + + } + + + public void flipBuffers(){ + //Log.v("test","Draw!"); + + try{ + + EGL10 egl = (EGL10)EGLContext.getEGL(); + GL10 gl = (GL10)mEGLContext.getGL(); + + egl.eglWaitNative(EGL10.EGL_NATIVE_RENDERABLE, null); + + //drawing here + + egl.eglWaitGL(); + + egl.eglSwapBuffers(mEGLDisplay, mEGLSurface); + + + }catch(Exception e){ + Log.v("SDL", e + ""); + } + + } - private static native void nativePause(); } + +/* class TestRenderer implements GLSurfaceView.Renderer { public void onSurfaceCreated(GL10 gl, EGLConfig config) { nativeInit(); } + + public void onSurfaceChanged(GL10 gl, int w, int h) { //gl.glViewport(0, 0, w, h); nativeResize(w, h); @@ -75,4 +206,6 @@ public void onDrawFrame(GL10 gl) { private static native void nativeResize(int w, int h); private static native void nativeRender(); private static native void nativeDone(); + } +*/ diff --git a/src/video/android/SDL_androidgl.c b/src/video/android/SDL_androidgl.c index a6b9b0bad..d01682a4c 100644 --- a/src/video/android/SDL_androidgl.c +++ b/src/video/android/SDL_androidgl.c @@ -41,8 +41,7 @@ /* These things are in the JNI android support */ -extern pthread_mutex_t mSDLRenderMutex; -extern pthread_cond_t mSDLRenderCondition; +extern void sdl_create_context(); extern void sdl_render(); /* GL functions */ @@ -68,7 +67,7 @@ int *Android_GL_GetVisual(_THIS, Display * display, int screen){ */ SDL_GLContext Android_GL_CreateContext(_THIS, SDL_Window * window){ - __android_log_print(ANDROID_LOG_INFO, "SDL", "[STUB] GL_CreateContext\n"); + sdl_create_context(); return 1; } @@ -89,16 +88,7 @@ int Android_GL_GetSwapInterval(_THIS){ } void Android_GL_SwapWindow(_THIS, SDL_Window * window){ - -/* - pthread_mutex_lock(&mSDLRenderMutex); - pthread_cond_wait(&mSDLRenderCondition, &mSDLRenderMutex); - pthread_mutex_unlock(&mSDLRenderMutex); -*/ - - //__android_log_print(ANDROID_LOG_INFO, "SDL", "[STUB] GL_SwapWindow\n"); sdl_render(); - } void Android_GL_DeleteContext(_THIS, SDL_GLContext context){