2011-01-06 17:12:31 -08:00
|
|
|
package org.libsdl.app;
|
|
|
|
|
|
|
|
import javax.microedition.khronos.egl.EGLConfig;
|
|
|
|
import javax.microedition.khronos.opengles.GL10;
|
|
|
|
import javax.microedition.khronos.egl.*;
|
|
|
|
|
|
|
|
import android.app.*;
|
|
|
|
import android.content.*;
|
|
|
|
import android.view.*;
|
|
|
|
import android.os.*;
|
|
|
|
import android.util.Log;
|
|
|
|
import android.graphics.*;
|
|
|
|
import android.text.method.*;
|
|
|
|
import android.text.*;
|
|
|
|
import android.media.*;
|
|
|
|
import android.hardware.*;
|
|
|
|
import android.content.*;
|
|
|
|
|
|
|
|
import java.lang.*;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
SDL Activity
|
|
|
|
*/
|
|
|
|
public class SDLActivity extends Activity {
|
|
|
|
|
2011-01-12 14:53:23 -08:00
|
|
|
// Main components
|
2011-01-06 17:12:31 -08:00
|
|
|
private static SDLActivity mSingleton;
|
|
|
|
private static SDLSurface mSurface;
|
|
|
|
|
2011-01-12 14:53:23 -08:00
|
|
|
// Audio
|
2011-01-06 17:12:31 -08:00
|
|
|
private static AudioTrack mAudioTrack;
|
|
|
|
|
2011-01-12 14:53:23 -08:00
|
|
|
// Load the .so
|
2011-01-06 17:12:31 -08:00
|
|
|
static {
|
|
|
|
System.loadLibrary("SDL");
|
|
|
|
System.loadLibrary("main");
|
|
|
|
}
|
|
|
|
|
2011-01-12 14:53:23 -08:00
|
|
|
// Setup
|
2011-01-06 17:12:31 -08:00
|
|
|
protected void onCreate(Bundle savedInstanceState) {
|
2011-01-12 17:53:06 -08:00
|
|
|
//Log.v("SDL", "onCreate()");
|
2011-01-06 17:12:31 -08:00
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
|
2011-01-12 14:53:23 -08:00
|
|
|
// So we can call stuff from static callbacks
|
2011-01-06 17:12:31 -08:00
|
|
|
mSingleton = this;
|
|
|
|
|
2011-01-12 14:53:23 -08:00
|
|
|
// Set up the surface
|
2011-01-06 17:12:31 -08:00
|
|
|
mSurface = new SDLSurface(getApplication());
|
|
|
|
setContentView(mSurface);
|
|
|
|
SurfaceHolder holder = mSurface.getHolder();
|
|
|
|
holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
|
|
|
|
}
|
|
|
|
|
2011-01-12 14:29:01 -08:00
|
|
|
// Events
|
2011-01-06 17:12:31 -08:00
|
|
|
protected void onPause() {
|
2011-01-12 17:53:06 -08:00
|
|
|
//Log.v("SDL", "onPause()");
|
2011-01-06 17:12:31 -08:00
|
|
|
super.onPause();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void onResume() {
|
2011-01-12 17:53:06 -08:00
|
|
|
//Log.v("SDL", "onResume()");
|
2011-01-06 17:12:31 -08:00
|
|
|
super.onResume();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-12 14:29:01 -08:00
|
|
|
// C functions we call
|
2011-01-06 17:12:31 -08:00
|
|
|
public static native void nativeInit();
|
|
|
|
public static native void nativeQuit();
|
|
|
|
public static native void onNativeKeyDown(int keycode);
|
|
|
|
public static native void onNativeKeyUp(int keycode);
|
|
|
|
public static native void onNativeTouch(int action, float x,
|
|
|
|
float y, float p);
|
|
|
|
public static native void onNativeResize(int x, int y, int format);
|
|
|
|
public static native void onNativeAccel(float x, float y, float z);
|
|
|
|
|
|
|
|
|
2011-01-12 14:53:23 -08:00
|
|
|
// Java functions called from C
|
2011-01-12 14:29:01 -08:00
|
|
|
private static void createGLContext() {
|
2011-01-06 17:12:31 -08:00
|
|
|
mSurface.initEGL();
|
|
|
|
}
|
|
|
|
|
2011-01-12 14:29:01 -08:00
|
|
|
public static void flipBuffers() {
|
2011-01-06 17:12:31 -08:00
|
|
|
mSurface.flipEGL();
|
|
|
|
}
|
|
|
|
|
2011-01-12 14:29:01 -08:00
|
|
|
public static void updateAudio(byte [] buf) {
|
2011-01-06 17:12:31 -08:00
|
|
|
|
2011-01-12 17:53:06 -08:00
|
|
|
if(mAudioTrack == null) {
|
|
|
|
// Hardcoded things are bad. FIXME when we have more sound stuff
|
|
|
|
// working properly.
|
|
|
|
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
|
|
|
|
11025,
|
|
|
|
AudioFormat.CHANNEL_CONFIGURATION_MONO,
|
|
|
|
AudioFormat.ENCODING_PCM_8BIT,
|
|
|
|
2048,
|
|
|
|
AudioTrack.MODE_STREAM);
|
2011-01-06 17:12:31 -08:00
|
|
|
}
|
2011-01-12 17:53:06 -08:00
|
|
|
|
2011-01-06 17:12:31 -08:00
|
|
|
mAudioTrack.write(buf, 0, buf.length);
|
|
|
|
mAudioTrack.play();
|
|
|
|
|
2011-01-12 17:53:06 -08:00
|
|
|
Log.v("SDL", "Played some audio");
|
2011-01-06 17:12:31 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Simple nativeInit() runnable
|
|
|
|
*/
|
2011-01-12 14:29:01 -08:00
|
|
|
class SDLMain implements Runnable {
|
|
|
|
public void run() {
|
|
|
|
// Runs SDL_main()
|
2011-01-06 17:12:31 -08:00
|
|
|
SDLActivity.nativeInit();
|
|
|
|
|
2011-01-12 17:53:06 -08:00
|
|
|
//Log.v("SDL", "SDL thread terminated");
|
2011-01-06 17:12:31 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
SDLSurface. This is what we draw on, so we need to know when it's created
|
|
|
|
in order to do anything useful.
|
|
|
|
|
|
|
|
Because of this, that's where we set up the SDL thread
|
|
|
|
*/
|
|
|
|
class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
|
|
|
View.OnKeyListener, View.OnTouchListener, SensorEventListener {
|
|
|
|
|
2011-01-12 14:29:01 -08:00
|
|
|
// This is what SDL runs in. It invokes SDL_main(), eventually
|
2011-01-06 17:12:31 -08:00
|
|
|
private Thread mSDLThread;
|
|
|
|
|
2011-01-12 14:29:01 -08:00
|
|
|
// EGL private objects
|
2011-01-06 17:12:31 -08:00
|
|
|
private EGLContext mEGLContext;
|
|
|
|
private EGLSurface mEGLSurface;
|
|
|
|
private EGLDisplay mEGLDisplay;
|
|
|
|
|
2011-01-12 14:29:01 -08:00
|
|
|
// Sensors
|
2011-01-06 17:12:31 -08:00
|
|
|
private static SensorManager mSensorManager;
|
|
|
|
|
2011-01-12 14:29:01 -08:00
|
|
|
// Startup
|
2011-01-06 17:12:31 -08:00
|
|
|
public SDLSurface(Context context) {
|
|
|
|
super(context);
|
|
|
|
getHolder().addCallback(this);
|
|
|
|
|
|
|
|
setFocusable(true);
|
|
|
|
setFocusableInTouchMode(true);
|
|
|
|
requestFocus();
|
|
|
|
setOnKeyListener(this);
|
|
|
|
setOnTouchListener(this);
|
2011-01-12 14:29:01 -08:00
|
|
|
|
2011-01-06 17:12:31 -08:00
|
|
|
mSensorManager = (SensorManager)context.getSystemService("sensor");
|
|
|
|
}
|
|
|
|
|
2011-01-12 14:29:01 -08:00
|
|
|
// Called when we have a valid drawing surface
|
2011-01-06 17:12:31 -08:00
|
|
|
public void surfaceCreated(SurfaceHolder holder) {
|
2011-01-12 17:53:06 -08:00
|
|
|
//Log.v("SDL", "surfaceCreated()");
|
|
|
|
|
|
|
|
enableSensor(Sensor.TYPE_ACCELEROMETER, true);
|
2011-01-06 17:12:31 -08:00
|
|
|
}
|
|
|
|
|
2011-01-12 14:29:01 -08:00
|
|
|
// Called when we lose the surface
|
2011-01-06 17:12:31 -08:00
|
|
|
public void surfaceDestroyed(SurfaceHolder holder) {
|
2011-01-12 17:53:06 -08:00
|
|
|
//Log.v("SDL", "surfaceDestroyed()");
|
2011-01-12 14:29:01 -08:00
|
|
|
|
|
|
|
// Send a quit message to the application
|
2011-01-06 17:12:31 -08:00
|
|
|
SDLActivity.nativeQuit();
|
|
|
|
|
2011-01-12 14:29:01 -08:00
|
|
|
// Now wait for the SDL thread to quit
|
|
|
|
if (mSDLThread != null) {
|
2011-01-12 17:53:06 -08:00
|
|
|
//synchronized (mSDLThread) {
|
|
|
|
try {
|
|
|
|
mSDLThread.join();
|
|
|
|
} catch(Exception e) {
|
|
|
|
Log.v("SDL", "Problem stopping thread: " + e);
|
|
|
|
}
|
|
|
|
//}
|
|
|
|
mSDLThread = null;
|
|
|
|
|
|
|
|
//Log.v("SDL", "Finished waiting for SDL thread");
|
2011-01-06 17:12:31 -08:00
|
|
|
}
|
2011-01-12 17:53:06 -08:00
|
|
|
|
|
|
|
enableSensor(Sensor.TYPE_ACCELEROMETER, false);
|
2011-01-06 17:12:31 -08:00
|
|
|
}
|
|
|
|
|
2011-01-12 14:29:01 -08:00
|
|
|
// Called when the surface is resized
|
|
|
|
public void surfaceChanged(SurfaceHolder holder,
|
|
|
|
int format, int width, int height) {
|
2011-01-12 17:53:06 -08:00
|
|
|
//Log.v("SDL", "surfaceChanged()");
|
2011-01-12 14:29:01 -08:00
|
|
|
|
2011-01-12 19:33:29 -08:00
|
|
|
int sdlFormat = 0x85151002; // SDL_PIXELFORMAT_RGB565 by default
|
2011-01-12 14:29:01 -08:00
|
|
|
switch (format) {
|
|
|
|
case PixelFormat.A_8:
|
2011-01-12 17:53:06 -08:00
|
|
|
Log.v("SDL", "pixel format A_8");
|
2011-01-12 14:29:01 -08:00
|
|
|
break;
|
|
|
|
case PixelFormat.LA_88:
|
2011-01-12 17:53:06 -08:00
|
|
|
Log.v("SDL", "pixel format LA_88");
|
2011-01-12 14:29:01 -08:00
|
|
|
break;
|
|
|
|
case PixelFormat.L_8:
|
2011-01-12 17:53:06 -08:00
|
|
|
Log.v("SDL", "pixel format L_8");
|
2011-01-12 14:29:01 -08:00
|
|
|
break;
|
|
|
|
case PixelFormat.RGBA_4444:
|
2011-01-12 17:53:06 -08:00
|
|
|
Log.v("SDL", "pixel format RGBA_4444");
|
2011-01-12 14:53:23 -08:00
|
|
|
sdlFormat = 0x85421002; // SDL_PIXELFORMAT_RGBA4444
|
2011-01-12 14:29:01 -08:00
|
|
|
break;
|
|
|
|
case PixelFormat.RGBA_5551:
|
2011-01-12 17:53:06 -08:00
|
|
|
Log.v("SDL", "pixel format RGBA_5551");
|
2011-01-12 14:53:23 -08:00
|
|
|
sdlFormat = 0x85441002; // SDL_PIXELFORMAT_RGBA5551
|
2011-01-12 14:29:01 -08:00
|
|
|
break;
|
|
|
|
case PixelFormat.RGBA_8888:
|
2011-01-12 17:53:06 -08:00
|
|
|
Log.v("SDL", "pixel format RGBA_8888");
|
2011-01-12 14:29:01 -08:00
|
|
|
sdlFormat = 0x86462004; // SDL_PIXELFORMAT_RGBA8888
|
|
|
|
break;
|
|
|
|
case PixelFormat.RGBX_8888:
|
2011-01-12 17:53:06 -08:00
|
|
|
Log.v("SDL", "pixel format RGBX_8888");
|
2011-01-12 14:29:01 -08:00
|
|
|
sdlFormat = 0x86262004; // SDL_PIXELFORMAT_RGBX8888
|
|
|
|
break;
|
|
|
|
case PixelFormat.RGB_332:
|
2011-01-12 17:53:06 -08:00
|
|
|
Log.v("SDL", "pixel format RGB_332");
|
2011-01-12 14:29:01 -08:00
|
|
|
sdlFormat = 0x84110801; // SDL_PIXELFORMAT_RGB332
|
|
|
|
break;
|
|
|
|
case PixelFormat.RGB_565:
|
2011-01-12 17:53:06 -08:00
|
|
|
Log.v("SDL", "pixel format RGB_565");
|
2011-01-12 14:29:01 -08:00
|
|
|
sdlFormat = 0x85151002; // SDL_PIXELFORMAT_RGB565
|
|
|
|
break;
|
|
|
|
case PixelFormat.RGB_888:
|
2011-01-12 17:53:06 -08:00
|
|
|
Log.v("SDL", "pixel format RGB_888");
|
2011-01-12 14:29:01 -08:00
|
|
|
// Not sure this is right, maybe SDL_PIXELFORMAT_RGB24 instead?
|
|
|
|
sdlFormat = 0x86161804; // SDL_PIXELFORMAT_RGB888
|
|
|
|
break;
|
2011-01-12 19:33:29 -08:00
|
|
|
default:
|
|
|
|
Log.v("SDL", "pixel format unknown " + format);
|
|
|
|
break;
|
2011-01-12 14:29:01 -08:00
|
|
|
}
|
2011-01-12 16:35:03 -08:00
|
|
|
SDLActivity.onNativeResize(width, height, sdlFormat);
|
2011-01-12 14:29:01 -08:00
|
|
|
|
|
|
|
// Now start up the C app thread
|
|
|
|
if (mSDLThread == null) {
|
|
|
|
mSDLThread = new Thread(new SDLMain(), "SDLThread");
|
|
|
|
mSDLThread.start();
|
|
|
|
}
|
2011-01-06 17:12:31 -08:00
|
|
|
}
|
|
|
|
|
2011-01-12 14:53:23 -08:00
|
|
|
// unused
|
2011-01-06 17:12:31 -08:00
|
|
|
public void onDraw(Canvas canvas) {}
|
|
|
|
|
|
|
|
|
2011-01-12 14:29:01 -08:00
|
|
|
// EGL functions
|
|
|
|
public boolean initEGL() {
|
|
|
|
Log.v("SDL", "Starting up");
|
|
|
|
|
|
|
|
try {
|
2011-01-06 17:12:31 -08:00
|
|
|
|
|
|
|
EGL10 egl = (EGL10)EGLContext.getEGL();
|
|
|
|
|
|
|
|
EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
|
|
|
|
|
|
|
|
int[] version = new int[2];
|
|
|
|
egl.eglInitialize(dpy, version);
|
|
|
|
|
|
|
|
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];
|
|
|
|
|
|
|
|
EGLContext ctx = egl.eglCreateContext(dpy, config, EGL10.EGL_NO_CONTEXT, null);
|
|
|
|
|
|
|
|
EGLSurface surface = egl.eglCreateWindowSurface(dpy, config, this, null);
|
|
|
|
|
|
|
|
egl.eglMakeCurrent(dpy, surface, surface, ctx);
|
|
|
|
|
|
|
|
mEGLContext = ctx;
|
|
|
|
mEGLDisplay = dpy;
|
|
|
|
mEGLSurface = surface;
|
2011-01-12 14:29:01 -08:00
|
|
|
|
|
|
|
} catch(Exception e) {
|
2011-01-06 17:12:31 -08:00
|
|
|
Log.v("SDL", e + "");
|
2011-01-12 17:53:06 -08:00
|
|
|
for(StackTraceElement s : e.getStackTrace()) {
|
2011-01-06 17:12:31 -08:00
|
|
|
Log.v("SDL", s.toString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-01-12 14:29:01 -08:00
|
|
|
// EGL buffer flip
|
|
|
|
public void flipEGL() {
|
|
|
|
try {
|
2011-01-06 17:12:31 -08:00
|
|
|
EGL10 egl = (EGL10)EGLContext.getEGL();
|
|
|
|
|
|
|
|
egl.eglWaitNative(EGL10.EGL_NATIVE_RENDERABLE, null);
|
|
|
|
|
2011-01-12 14:53:23 -08:00
|
|
|
// drawing here
|
2011-01-06 17:12:31 -08:00
|
|
|
|
|
|
|
egl.eglWaitGL();
|
|
|
|
|
|
|
|
egl.eglSwapBuffers(mEGLDisplay, mEGLSurface);
|
|
|
|
|
|
|
|
|
2011-01-12 14:29:01 -08:00
|
|
|
} catch(Exception e) {
|
2011-01-06 17:12:31 -08:00
|
|
|
Log.v("SDL", "flipEGL(): " + e);
|
2011-01-12 17:53:06 -08:00
|
|
|
for(StackTraceElement s : e.getStackTrace()) {
|
2011-01-06 17:12:31 -08:00
|
|
|
Log.v("SDL", s.toString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-12 14:29:01 -08:00
|
|
|
// Key events
|
2011-01-12 17:53:06 -08:00
|
|
|
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
2011-01-06 17:12:31 -08:00
|
|
|
|
2011-01-12 14:29:01 -08:00
|
|
|
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
2011-01-12 19:33:29 -08:00
|
|
|
Log.v("SDL", "key down: " + keyCode);
|
2011-01-06 17:12:31 -08:00
|
|
|
SDLActivity.onNativeKeyDown(keyCode);
|
|
|
|
return true;
|
|
|
|
}
|
2011-01-12 14:29:01 -08:00
|
|
|
else if (event.getAction() == KeyEvent.ACTION_UP) {
|
2011-01-12 19:33:29 -08:00
|
|
|
Log.v("SDL", "key up: " + keyCode);
|
2011-01-06 17:12:31 -08:00
|
|
|
SDLActivity.onNativeKeyUp(keyCode);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-01-12 14:29:01 -08:00
|
|
|
// Touch events
|
|
|
|
public boolean onTouch(View v, MotionEvent event) {
|
2011-01-06 17:12:31 -08:00
|
|
|
|
|
|
|
int action = event.getAction();
|
|
|
|
float x = event.getX();
|
|
|
|
float y = event.getY();
|
|
|
|
float p = event.getPressure();
|
|
|
|
|
2011-01-12 14:53:23 -08:00
|
|
|
// TODO: Anything else we need to pass?
|
2011-01-06 17:12:31 -08:00
|
|
|
SDLActivity.onNativeTouch(action, x, y, p);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-01-12 14:29:01 -08:00
|
|
|
// Sensor events
|
|
|
|
public void enableSensor(int sensortype, boolean enabled) {
|
2011-01-12 14:53:23 -08:00
|
|
|
// TODO: This uses getDefaultSensor - what if we have >1 accels?
|
2011-01-12 14:29:01 -08:00
|
|
|
if (enabled) {
|
2011-01-06 17:12:31 -08:00
|
|
|
mSensorManager.registerListener(this,
|
|
|
|
mSensorManager.getDefaultSensor(sensortype),
|
|
|
|
SensorManager.SENSOR_DELAY_GAME, null);
|
2011-01-12 14:29:01 -08:00
|
|
|
} else {
|
2011-01-06 17:12:31 -08:00
|
|
|
mSensorManager.unregisterListener(this,
|
|
|
|
mSensorManager.getDefaultSensor(sensortype));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-12 14:29:01 -08:00
|
|
|
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
2011-01-12 14:53:23 -08:00
|
|
|
// TODO
|
2011-01-06 17:12:31 -08:00
|
|
|
}
|
|
|
|
|
2011-01-12 14:29:01 -08:00
|
|
|
public void onSensorChanged(SensorEvent event) {
|
|
|
|
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
|
|
|
|
SDLActivity.onNativeAccel(event.values[0],
|
|
|
|
event.values[1],
|
|
|
|
event.values[2]);
|
2011-01-06 17:12:31 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|