Commit 482a87c4 authored by Paul Hunkin's avatar Paul Hunkin

- Restructured threads and application structure.

- Moved to SurfaceView instead of GLSurfaceView
- Moved to C++ for the android library
parent 3ad2c1bd
...@@ -11,8 +11,8 @@ LOCAL_CFLAGS := -DANDROID_NDK \ ...@@ -11,8 +11,8 @@ LOCAL_CFLAGS := -DANDROID_NDK \
-I$(SDL)/include -I$(SDL)/include
LOCAL_SRC_FILES := \ LOCAL_SRC_FILES := \
importgl.c \ importgl.cpp \
app-android.c \ app-android.cpp \
lesson05.c \ lesson05.c \
LOCAL_LDLIBS := -lGLESv1_CM -ldl -llog -lSDL -lEGL -lgcc -L$(SDL) -L$(SDL)/build-scripts/android_libs/ LOCAL_LDLIBS := -lGLESv1_CM -ldl -llog -lSDL -lEGL -lgcc -L$(SDL) -L$(SDL)/build-scripts/android_libs/
......
/*******************************************************************************
Headers
*******************************************************************************/
#include <jni.h>
#include <sys/time.h>
#include <time.h>
#include <android/log.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <pthread.h>
#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");
}
/*******************************************************************************
Headers
*******************************************************************************/
#include <jni.h>
#include <sys/time.h>
#include <time.h>
#include <android/log.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <pthread.h>
#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 );
}
...@@ -2,66 +2,197 @@ package org.libsdl.android; ...@@ -2,66 +2,197 @@ package org.libsdl.android;
import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.egl.*;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.opengl.GLSurfaceView; import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.os.Bundle; import android.os.Bundle;
import android.view.MotionEvent; 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 { public class TestActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mGLView = new TestGLSurfaceView(this); mSurface = new SDLSurface(getApplication());
setContentView(mGLView); setContentView(mSurface);
SurfaceHolder holder = mSurface.getHolder();
holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
} }
@Override
protected void onPause() { protected void onPause() {
super.onPause(); super.onPause();
mGLView.onPause();
} }
@Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
mGLView.onResume();
//All set up. Start up SDL
} }
private GLSurfaceView mGLView; private static SDLSurface mSurface;
static { static {
System.loadLibrary("sanangeles"); 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 { class SDLThread implements Runnable{
public TestGLSurfaceView(Context context) { public void run(){
super(context); TestActivity.nativeInit();
mRenderer = new TestRenderer(); }
setRenderer(mRenderer); }
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) { public void surfaceDestroyed(SurfaceHolder holder) {
if (event.getAction() == MotionEvent.ACTION_DOWN) { Log.v("SDL","Surface destroyed");
nativePause(); }
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; 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 { class TestRenderer implements GLSurfaceView.Renderer {
public void onSurfaceCreated(GL10 gl, EGLConfig config) { public void onSurfaceCreated(GL10 gl, EGLConfig config) {
nativeInit(); nativeInit();
} }
public void onSurfaceChanged(GL10 gl, int w, int h) { public void onSurfaceChanged(GL10 gl, int w, int h) {
//gl.glViewport(0, 0, w, h); //gl.glViewport(0, 0, w, h);
nativeResize(w, h); nativeResize(w, h);
...@@ -75,4 +206,6 @@ class TestRenderer implements GLSurfaceView.Renderer { ...@@ -75,4 +206,6 @@ class TestRenderer implements GLSurfaceView.Renderer {
private static native void nativeResize(int w, int h); private static native void nativeResize(int w, int h);
private static native void nativeRender(); private static native void nativeRender();
private static native void nativeDone(); private static native void nativeDone();
} }
*/
...@@ -41,8 +41,7 @@ ...@@ -41,8 +41,7 @@
/* /*
These things are in the JNI android support These things are in the JNI android support
*/ */
extern pthread_mutex_t mSDLRenderMutex; extern void sdl_create_context();
extern pthread_cond_t mSDLRenderCondition;
extern void sdl_render(); extern void sdl_render();
/* GL functions */ /* GL functions */
...@@ -68,7 +67,7 @@ int *Android_GL_GetVisual(_THIS, Display * display, int screen){ ...@@ -68,7 +67,7 @@ int *Android_GL_GetVisual(_THIS, Display * display, int screen){
*/ */
SDL_GLContext Android_GL_CreateContext(_THIS, SDL_Window * window){ 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; return 1;
} }
...@@ -89,16 +88,7 @@ int Android_GL_GetSwapInterval(_THIS){ ...@@ -89,16 +88,7 @@ int Android_GL_GetSwapInterval(_THIS){
} }
void Android_GL_SwapWindow(_THIS, SDL_Window * window){ 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(); sdl_render();
} }
void Android_GL_DeleteContext(_THIS, SDL_GLContext context){ void Android_GL_DeleteContext(_THIS, SDL_GLContext context){
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment