[Scummvm-cvs-logs] scummvm master -> 2d4a64d18493b142b1899a822202015339733cfa

dhewg dhewg at wiibrew.org
Wed Mar 2 23:21:48 CET 2011


This automated email contains information about 11 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
807971f8af ANDROID: Don't use warning()/error() in a thread
2f008d0cd6 ANDROID: Don't use warning() in JNI functions
b84b56b248 COMMON: Remove newlines from debug()
2333a32697 ANDROID: Untangle JNI interweaving
bd7e3e9bb2 ANDROID: cleanup
82a9beff2b ANDROID: Move swapBuffers to the native side
d6e838e1b3 ANDROID: Merge FIND_METHODs
ccfe427eb5 ANDROID: Check for a surface in updateScreen()
25ef065a41 ANDROID: Implement pause/resume
c2d4cce429 ANDROID: On pause, put all threads in a coma
2d4a64d184 ANDROID: Properly release texture resources


Commit: 807971f8af9430ee19f66c7bac7cc9566fccf432
    https://github.com/scummvm/scummvm/commit/807971f8af9430ee19f66c7bac7cc9566fccf432
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-03-02T14:18:33-08:00

Commit Message:
ANDROID: Don't use warning()/error() in a thread

Changed paths:
    backends/platform/android/android.cpp




Commit: 2f008d0cd6ffa84071fe2f5c343ef19328cc83ae
    https://github.com/scummvm/scummvm/commit/2f008d0cd6ffa84071fe2f5c343ef19328cc83ae
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-03-02T14:18:33-08:00

Commit Message:
ANDROID: Don't use warning() in JNI functions

Changed paths:
    backends/platform/android/jni.cpp



diff --git a/backends/platform/android/jni.cpp b/backends/platform/android/jni.cpp
index 69d1083..99934fb 100644
--- a/backends/platform/android/jni.cpp
+++ b/backends/platform/android/jni.cpp
@@ -212,7 +212,7 @@ void JNI::getPluginDirectories(Common::FSList &dirs) {
 		(jobjectArray)env->CallObjectMethod(_jobj, _MID_getPluginDirectories);
 
 	if (env->ExceptionCheck()) {
-		warning("Error finding plugin directories");
+		LOGE("Error finding plugin directories");
 
 		env->ExceptionDescribe();
 		env->ExceptionClear();
@@ -230,7 +230,7 @@ void JNI::getPluginDirectories(Common::FSList &dirs) {
 		const char *path = env->GetStringUTFChars(path_obj, 0);
 
 		if (path == 0) {
-			warning("Error getting string characters from plugin directory");
+			LOGE("Error getting string characters from plugin directory");
 
 			env->ExceptionClear();
 			env->DeleteLocalRef(path_obj);
@@ -252,7 +252,7 @@ void JNI::setWindowCaption(const char *caption) {
 	env->CallVoidMethod(_jobj, _MID_setWindowCaption, java_caption);
 
 	if (env->ExceptionCheck()) {
-		warning("Failed to set window caption");
+		LOGE("Failed to set window caption");
 
 		env->ExceptionDescribe();
 		env->ExceptionClear();
@@ -268,7 +268,7 @@ void JNI::displayMessageOnOSD(const char *msg) {
 	env->CallVoidMethod(_jobj, _MID_displayMessageOnOSD, java_msg);
 
 	if (env->ExceptionCheck()) {
-		warning("Failed to display OSD message");
+		LOGE("Failed to display OSD message");
 
 		env->ExceptionDescribe();
 		env->ExceptionClear();
@@ -283,7 +283,7 @@ void JNI::showVirtualKeyboard(bool enable) {
 	env->CallVoidMethod(_jobj, _MID_showVirtualKeyboard, enable);
 
 	if (env->ExceptionCheck()) {
-		error("Error trying to show virtual keyboard");
+		LOGE("Error trying to show virtual keyboard");
 
 		env->ExceptionDescribe();
 		env->ExceptionClear();
@@ -299,7 +299,7 @@ void JNI::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
 		(jobjectArray)env->CallObjectMethod(_jobj, _MID_getSysArchives);
 
 	if (env->ExceptionCheck()) {
-		warning("Error finding system archive path");
+		LOGE("Error finding system archive path");
 
 		env->ExceptionDescribe();
 		env->ExceptionClear();
@@ -327,7 +327,7 @@ void JNI::setAudioPause() {
 	env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_flush);
 
 	if (env->ExceptionCheck()) {
-		warning("Error flushing AudioTrack");
+		LOGE("Error flushing AudioTrack");
 
 		env->ExceptionDescribe();
 		env->ExceptionClear();
@@ -336,7 +336,7 @@ void JNI::setAudioPause() {
 	env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_pause);
 
 	if (env->ExceptionCheck()) {
-		warning("Error setting AudioTrack: pause");
+		LOGE("Error setting AudioTrack: pause");
 
 		env->ExceptionDescribe();
 		env->ExceptionClear();
@@ -349,7 +349,7 @@ void JNI::setAudioPlay() {
 	env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_play);
 
 	if (env->ExceptionCheck()) {
-		warning("Error setting AudioTrack: play");
+		LOGE("Error setting AudioTrack: play");
 
 		env->ExceptionDescribe();
 		env->ExceptionClear();
@@ -362,7 +362,7 @@ void JNI::setAudioStop() {
 	env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_stop);
 
 	if (env->ExceptionCheck()) {
-		warning("Error setting AudioTrack: stop");
+		LOGE("Error setting AudioTrack: stop");
 
 		env->ExceptionDescribe();
 		env->ExceptionClear();


Commit: b84b56b2481bac8ad92ffe6870b28b288011bf6a
    https://github.com/scummvm/scummvm/commit/b84b56b2481bac8ad92ffe6870b28b288011bf6a
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-03-02T14:18:34-08:00

Commit Message:
COMMON: Remove newlines from debug()

They were interfering with my precious debug spew :P

Changed paths:
    common/config-manager.cpp



diff --git a/common/config-manager.cpp b/common/config-manager.cpp
index 0561f39..c8c0999 100644
--- a/common/config-manager.cpp
+++ b/common/config-manager.cpp
@@ -103,9 +103,9 @@ void ConfigManager::loadConfigFile(const String &filename) {
 	FSNode node(filename);
 	File cfg_file;
 	if (!cfg_file.open(node)) {
-		debug("Creating configuration file: %s\n", filename.c_str());
+		debug("Creating configuration file: %s", filename.c_str());
 	} else {
-		debug("Using configuration file: %s\n", _filename.c_str());
+		debug("Using configuration file: %s", _filename.c_str());
 		loadFromStream(cfg_file);
 	}
 }


Commit: 2333a32697cda8f5f73861856889001839f38f25
    https://github.com/scummvm/scummvm/commit/2333a32697cda8f5f73861856889001839f38f25
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-03-02T14:18:34-08:00

Commit Message:
ANDROID: Untangle JNI interweaving

- make the startup sequence more linear
- use SurfaceHolder events
- get rid of the surface lock
- remove unnecessary JNI calls
- make the ScummVM class implement Runnable
- cleanup

Changed paths:
    backends/platform/android/android.cpp
    backends/platform/android/android.h
    backends/platform/android/gfx.cpp
    backends/platform/android/jni.cpp
    backends/platform/android/jni.h
    backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
    backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java



diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index f886347..2af367e 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -103,6 +103,8 @@ OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) :
 	_audio_sample_rate(audio_sample_rate),
 	_audio_buffer_size(audio_buffer_size),
 	_screen_changeid(0),
+	_egl_surface_width(0),
+	_egl_surface_height(0),
 	_force_redraw(false),
 	_game_texture(0),
 	_overlay_texture(0),
@@ -126,11 +128,9 @@ OSystem_Android::~OSystem_Android() {
 	delete _overlay_texture;
 	delete _mouse_texture;
 
-	JNI::destroySurface();
-
 	delete _savefile;
-	delete _mixer;
 	delete _timer;
+	delete _mixer;
 	delete _fsFactory;
 
 	deleteMutex(_event_queue_lock);
@@ -303,21 +303,19 @@ void OSystem_Android::initBackend() {
 	_mixer = new Audio::MixerImpl(this, _audio_sample_rate);
 	_mixer->setReady(true);
 
-	JNI::initBackend();
-
 	_timer_thread_exit = false;
 	pthread_create(&_timer_thread, 0, timerThreadFunc, this);
 
 	_audio_thread_exit = false;
 	pthread_create(&_audio_thread, 0, audioThreadFunc, this);
 
-	OSystem::initBackend();
-
 	setupSurface();
 
 	// renice this thread to boost the audio thread
 	if (setpriority(PRIO_PROCESS, 0, 19) < 0)
 		warning("couldn't renice the main thread");
+
+	JNI::setReadyForEvents(true);
 }
 
 void OSystem_Android::addPluginDirectories(Common::FSList &dirs) const {
@@ -385,6 +383,28 @@ void OSystem_Android::setupKeymapper() {
 bool OSystem_Android::pollEvent(Common::Event &event) {
 	//ENTER();
 
+	if (pthread_self() == _main_thread) {
+		if (_screen_changeid != JNI::surface_changeid) {
+			if (JNI::egl_surface_width > 0 && JNI::egl_surface_height > 0) {
+				LOGD("initializing surface");
+
+				JNI::deinitSurface();
+				setupSurface();
+
+				event.type = Common::EVENT_SCREEN_CHANGED;
+
+				return true;
+			}
+
+			LOGD("deinitialiting surface");
+
+			_screen_changeid = JNI::surface_changeid;
+			JNI::deinitSurface();
+
+			// TODO prevent swapBuffers
+		}
+	}
+
 	lockMutex(_event_queue_lock);
 
 	if (_event_queue.empty()) {
@@ -433,12 +453,6 @@ bool OSystem_Android::pollEvent(Common::Event &event) {
 		}
 		break;
 	}
-	case Common::EVENT_SCREEN_CHANGED:
-		debug("EVENT_SCREEN_CHANGED");
-		_screen_changeid++;
-		JNI::destroySurface();
-		setupSurface();
-		break;
 	default:
 		break;
 	}
@@ -525,11 +539,15 @@ void OSystem_Android::deleteMutex(MutexRef mutex) {
 void OSystem_Android::quit() {
 	ENTER();
 
+	JNI::setReadyForEvents(false);
+
 	_audio_thread_exit = true;
 	pthread_join(_audio_thread, 0);
 
 	_timer_thread_exit = true;
 	pthread_join(_timer_thread, 0);
+
+	JNI::deinitSurface();
 }
 
 void OSystem_Android::setWindowCaption(const char *caption) {
diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h
index f4e9d61..aa6016e 100644
--- a/backends/platform/android/android.h
+++ b/backends/platform/android/android.h
@@ -151,10 +151,6 @@ public:
 	virtual void initBackend();
 	void addPluginDirectories(Common::FSList &dirs) const;
 	void enableZoning(bool enable) { _enable_zoning = enable; }
-	void setSurfaceSize(int width, int height) {
-		_egl_surface_width = width;
-		_egl_surface_height = height;
-	}
 
 	virtual bool hasFeature(Feature f);
 	virtual void setFeatureState(Feature f, bool enable);
@@ -166,10 +162,7 @@ public:
 	virtual int getGraphicsMode() const;
 	virtual void initSize(uint width, uint height,
 							const Graphics::PixelFormat *format);
-
-	virtual int getScreenChangeID() const {
-		return _screen_changeid;
-	}
+	virtual int getScreenChangeID() const;
 
 	virtual int16 getHeight();
 	virtual int16 getWidth();
diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp
index 8601a3b..49f3d40 100644
--- a/backends/platform/android/gfx.cpp
+++ b/backends/platform/android/gfx.cpp
@@ -65,8 +65,13 @@ int OSystem_Android::getGraphicsMode() const {
 void OSystem_Android::setupSurface() {
 	ENTER();
 
-	if (!JNI::setupSurface())
-		return;
+	_screen_changeid = JNI::surface_changeid;
+	JNI::initSurface();
+
+	_egl_surface_width = JNI::egl_surface_width;
+	_egl_surface_height = JNI::egl_surface_height;
+
+	assert(_egl_surface_width > 0 && _egl_surface_height > 0);
 
 	// EGL set up with a new surface.  Initialise OpenGLES context.
 	GLESTexture::initGLExtensions();
@@ -148,6 +153,10 @@ void OSystem_Android::initSize(uint width, uint height,
 	_mouse_texture->allocBuffer(20, 20);
 }
 
+int OSystem_Android::getScreenChangeID() const {
+	return _screen_changeid;
+}
+
 int16 OSystem_Android::getHeight() {
 	return _game_texture->height();
 }
@@ -279,10 +288,14 @@ void OSystem_Android::updateScreen() {
 
 	GLCALL(glPopMatrix());
 
-	if (!JNI::swapBuffers()) {
-		// Context lost -> need to reinit GL
-		JNI::destroySurface();
+	int res = JNI::swapBuffers();
+
+	if (res) {
+		warning("swapBuffers returned 0x%x", res);
+#if 0
+		JNI::initSurface();
 		setupSurface();
+#endif
 	}
 }
 
diff --git a/backends/platform/android/jni.cpp b/backends/platform/android/jni.cpp
index 99934fb..28a03d0 100644
--- a/backends/platform/android/jni.cpp
+++ b/backends/platform/android/jni.cpp
@@ -44,6 +44,11 @@ jobject JNI::_jobj_audio_track = 0;
 Common::Archive *JNI::_asset_archive = 0;
 OSystem_Android *JNI::_system = 0;
 
+int JNI::surface_changeid = 0;
+int JNI::egl_surface_width = 0;
+int JNI::egl_surface_height = 0;
+bool JNI::_ready_for_events = 0;
+
 jfieldID JNI::_FID_Event_type = 0;
 jfieldID JNI::_FID_Event_synthetic = 0;
 jfieldID JNI::_FID_Event_kbd_keycode = 0;
@@ -55,13 +60,12 @@ jfieldID JNI::_FID_Event_mouse_relative = 0;
 
 jmethodID JNI::_MID_displayMessageOnOSD = 0;
 jmethodID JNI::_MID_setWindowCaption = 0;
-jmethodID JNI::_MID_initBackend = 0;
 jmethodID JNI::_MID_showVirtualKeyboard = 0;
 jmethodID JNI::_MID_getSysArchives = 0;
 jmethodID JNI::_MID_getPluginDirectories = 0;
-jmethodID JNI::_MID_setupScummVMSurface = 0;
-jmethodID JNI::_MID_destroyScummVMSurface = 0;
 jmethodID JNI::_MID_swapBuffers = 0;
+jmethodID JNI::_MID_initSurface = 0;
+jmethodID JNI::_MID_deinitSurface = 0;
 
 jmethodID JNI::_MID_AudioTrack_flush = 0;
 jmethodID JNI::_MID_AudioTrack_pause = 0;
@@ -73,16 +77,16 @@ const JNINativeMethod JNI::_natives[] = {
 	{ "create", "(Landroid/content/res/AssetManager;"
 				"Landroid/media/AudioTrack;II)V",
 		(void *)JNI::create },
-	{ "nativeDestroy", "()V",
+	{ "destroy", "()V",
 		(void *)JNI::destroy },
-	{ "scummVMMain", "([Ljava/lang/String;)I",
+	{ "setSurface", "(II)V",
+	 	(void *)JNI::setSurface },
+	{ "main", "([Ljava/lang/String;)I",
 	 	(void *)JNI::main },
 	{ "pushEvent", "(Lorg/inodes/gus/scummvm/Event;)V",
 		(void *)JNI::pushEvent },
 	{ "enableZoning", "(Z)V",
 		(void *)JNI::enableZoning },
-	{ "setSurfaceSize", "(II)V",
-		(void *)JNI::setSurfaceSize },
 };
 
 JNI::JNI() {
@@ -178,6 +182,10 @@ void JNI::detachThread() {
 	}
 }
 
+void JNI::setReadyForEvents(bool ready) {
+	_ready_for_events = ready;
+}
+
 void JNI::throwByName(JNIEnv *env, const char *name, const char *msg) {
 	jclass cls = env->FindClass(name);
 
@@ -188,61 +196,26 @@ void JNI::throwByName(JNIEnv *env, const char *name, const char *msg) {
 	env->DeleteLocalRef(cls);
 }
 
-// calls to the dark side
-
-void JNI::initBackend() {
-	JNIEnv *env = JNI::getEnv();
-
-	env->CallVoidMethod(_jobj, _MID_initBackend);
-
-	if (env->ExceptionCheck()) {
-		error("Error in Java initBackend");
-
-		env->ExceptionDescribe();
-		env->ExceptionClear();
-
-		// TODO now what?
-	}
+void JNI::throwRuntimeException(JNIEnv *env, const char *msg) {
+	throwByName(env, "java/lang/RuntimeException", msg);
 }
 
-void JNI::getPluginDirectories(Common::FSList &dirs) {
+// calls to the dark side
+
+void JNI::displayMessageOnOSD(const char *msg) {
 	JNIEnv *env = JNI::getEnv();
+	jstring java_msg = env->NewStringUTF(msg);
 
-	jobjectArray array =
-		(jobjectArray)env->CallObjectMethod(_jobj, _MID_getPluginDirectories);
+	env->CallVoidMethod(_jobj, _MID_displayMessageOnOSD, java_msg);
 
 	if (env->ExceptionCheck()) {
-		LOGE("Error finding plugin directories");
+		LOGE("Failed to display OSD message");
 
 		env->ExceptionDescribe();
 		env->ExceptionClear();
-
-		return;
 	}
 
-	jsize size = env->GetArrayLength(array);
-	for (jsize i = 0; i < size; ++i) {
-		jstring path_obj = (jstring)env->GetObjectArrayElement(array, i);
-
-		if (path_obj == 0)
-			continue;
-
-		const char *path = env->GetStringUTFChars(path_obj, 0);
-
-		if (path == 0) {
-			LOGE("Error getting string characters from plugin directory");
-
-			env->ExceptionClear();
-			env->DeleteLocalRef(path_obj);
-
-			continue;
-		}
-
-		dirs.push_back(Common::FSNode(path));
-
-		env->ReleaseStringUTFChars(path_obj, path);
-		env->DeleteLocalRef(path_obj);
-	}
+	env->DeleteLocalRef(java_msg);
 }
 
 void JNI::setWindowCaption(const char *caption) {
@@ -261,22 +234,6 @@ void JNI::setWindowCaption(const char *caption) {
 	env->DeleteLocalRef(java_caption);
 }
 
-void JNI::displayMessageOnOSD(const char *msg) {
-	JNIEnv *env = JNI::getEnv();
-	jstring java_msg = env->NewStringUTF(msg);
-
-	env->CallVoidMethod(_jobj, _MID_displayMessageOnOSD, java_msg);
-
-	if (env->ExceptionCheck()) {
-		LOGE("Failed to display OSD message");
-
-		env->ExceptionDescribe();
-		env->ExceptionClear();
-	}
-
-	env->DeleteLocalRef(java_msg);
-}
-
 void JNI::showVirtualKeyboard(bool enable) {
 	JNIEnv *env = JNI::getEnv();
 
@@ -321,6 +278,72 @@ void JNI::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
 	}
 }
 
+void JNI::getPluginDirectories(Common::FSList &dirs) {
+	JNIEnv *env = JNI::getEnv();
+
+	jobjectArray array =
+		(jobjectArray)env->CallObjectMethod(_jobj, _MID_getPluginDirectories);
+
+	if (env->ExceptionCheck()) {
+		LOGE("Error finding plugin directories");
+
+		env->ExceptionDescribe();
+		env->ExceptionClear();
+
+		return;
+	}
+
+	jsize size = env->GetArrayLength(array);
+	for (jsize i = 0; i < size; ++i) {
+		jstring path_obj = (jstring)env->GetObjectArrayElement(array, i);
+
+		if (path_obj == 0)
+			continue;
+
+		const char *path = env->GetStringUTFChars(path_obj, 0);
+
+		if (path == 0) {
+			LOGE("Error getting string characters from plugin directory");
+
+			env->ExceptionClear();
+			env->DeleteLocalRef(path_obj);
+
+			continue;
+		}
+
+		dirs.push_back(Common::FSNode(path));
+
+		env->ReleaseStringUTFChars(path_obj, path);
+		env->DeleteLocalRef(path_obj);
+	}
+}
+
+void JNI::initSurface() {
+	JNIEnv *env = JNI::getEnv();
+
+	env->CallVoidMethod(_jobj, _MID_initSurface);
+
+	if (env->ExceptionCheck()) {
+		LOGE("initSurface failed");
+
+		env->ExceptionDescribe();
+		env->ExceptionClear();
+	}
+}
+
+void JNI::deinitSurface() {
+	JNIEnv *env = JNI::getEnv();
+
+	env->CallVoidMethod(_jobj, _MID_deinitSurface);
+
+	if (env->ExceptionCheck()) {
+		LOGE("deinitSurface failed");
+
+		env->ExceptionDescribe();
+		env->ExceptionClear();
+	}
+}
+
 void JNI::setAudioPause() {
 	JNIEnv *env = JNI::getEnv();
 
@@ -396,13 +419,12 @@ void JNI::create(JNIEnv *env, jobject self, jobject am, jobject at,
 
 	FIND_METHOD(setWindowCaption, "(Ljava/lang/String;)V");
 	FIND_METHOD(displayMessageOnOSD, "(Ljava/lang/String;)V");
-	FIND_METHOD(initBackend, "()V");
 	FIND_METHOD(showVirtualKeyboard, "(Z)V");
 	FIND_METHOD(getSysArchives, "()[Ljava/lang/String;");
 	FIND_METHOD(getPluginDirectories, "()[Ljava/lang/String;");
-	FIND_METHOD(setupScummVMSurface, "()V");
-	FIND_METHOD(destroyScummVMSurface, "()V");
-	FIND_METHOD(swapBuffers, "()Z");
+	FIND_METHOD(swapBuffers, "()I");
+	FIND_METHOD(initSurface, "()V");
+	FIND_METHOD(deinitSurface, "()V");
 
 #undef FIND_METHOD
 
@@ -428,16 +450,12 @@ void JNI::create(JNIEnv *env, jobject self, jobject am, jobject at,
 }
 
 void JNI::destroy(JNIEnv *env, jobject self) {
-	if (!_system)
-		return;
+	delete _asset_archive;
+	_asset_archive = 0;
 
-	OSystem_Android *tmp = _system;
+	delete _system;
 	g_system = 0;
 	_system = 0;
-	delete tmp;
-
-	delete _asset_archive;
-	_asset_archive = 0;
 
 	// see above
 	//JNI::getEnv()->DeleteWeakGlobalRef(_jobj);
@@ -445,6 +463,12 @@ void JNI::destroy(JNIEnv *env, jobject self) {
 	JNI::getEnv()->DeleteGlobalRef(_jobj);
 }
 
+void JNI::setSurface(JNIEnv *env, jobject self, jint width, jint height) {
+	egl_surface_width = width;
+	egl_surface_height = height;
+	surface_changeid++;
+}
+
 jint JNI::main(JNIEnv *env, jobject self, jobjectArray args) {
 	assert(_system);
 
@@ -489,7 +513,7 @@ jint JNI::main(JNIEnv *env, jobject self, jobjectArray args) {
 
 	res = scummvm_main(argc, argv);
 
-	LOGI("Exiting scummvm_main");
+	LOGI("scummvm_main exited with code %d", res);
 
 	_system->quit();
 
@@ -514,6 +538,10 @@ cleanup:
 }
 
 void JNI::pushEvent(JNIEnv *env, jobject self, jobject java_event) {
+	// drop events until we're ready and after we quit
+	if (!_ready_for_events)
+		return;
+
 	assert(_system);
 
 	Common::Event event;
@@ -565,11 +593,5 @@ void JNI::enableZoning(JNIEnv *env, jobject self, jboolean enable) {
 	_system->enableZoning(enable);
 }
 
-void JNI::setSurfaceSize(JNIEnv *env, jobject self, jint width, jint height) {
-	assert(_system);
-
-	_system->setSurfaceSize(width, height);
-}
-
 #endif
 
diff --git a/backends/platform/android/jni.h b/backends/platform/android/jni.h
index 0bc6498..0005136 100644
--- a/backends/platform/android/jni.h
+++ b/backends/platform/android/jni.h
@@ -41,6 +41,10 @@ private:
 	virtual ~JNI();
 
 public:
+	static int surface_changeid;
+	static int egl_surface_width;
+	static int egl_surface_height;
+
 	static jint onLoad(JavaVM *vm);
 
 	static JNIEnv *getEnv();
@@ -48,16 +52,17 @@ public:
 	static void attachThread();
 	static void detachThread();
 
-	static void initBackend();
+	static void setReadyForEvents(bool ready);
+
 	static void getPluginDirectories(Common::FSList &dirs);
 	static void setWindowCaption(const char *caption);
 	static void displayMessageOnOSD(const char *msg);
 	static void showVirtualKeyboard(bool enable);
 	static void addSysArchivesToSearchSet(Common::SearchSet &s, int priority);
 
-	static inline bool setupSurface();
-	static inline void destroySurface();
-	static inline bool swapBuffers();
+	static inline int swapBuffers();
+	static void initSurface();
+	static void deinitSurface();
 
 	static void setAudioPause();
 	static void setAudioPlay();
@@ -75,6 +80,8 @@ private:
 	static Common::Archive *_asset_archive;
 	static OSystem_Android *_system;
 
+	static bool _ready_for_events;
+
 	static jfieldID _FID_Event_type;
 	static jfieldID _FID_Event_synthetic;
 	static jfieldID _FID_Event_kbd_keycode;
@@ -87,13 +94,12 @@ private:
 
 	static jmethodID _MID_displayMessageOnOSD;
 	static jmethodID _MID_setWindowCaption;
-	static jmethodID _MID_initBackend;
 	static jmethodID _MID_showVirtualKeyboard;
 	static jmethodID _MID_getSysArchives;
 	static jmethodID _MID_getPluginDirectories;
-	static jmethodID _MID_setupScummVMSurface;
-	static jmethodID _MID_destroyScummVMSurface;
 	static jmethodID _MID_swapBuffers;
+	static jmethodID _MID_initSurface;
+	static jmethodID _MID_deinitSurface;
 
 	static jmethodID _MID_AudioTrack_flush;
 	static jmethodID _MID_AudioTrack_pause;
@@ -104,40 +110,24 @@ private:
 	static const JNINativeMethod _natives[];
 
 	static void throwByName(JNIEnv *env, const char *name, const char *msg);
+	static void throwRuntimeException(JNIEnv *env, const char *msg);
 
 	// natives for the dark side
 	static void create(JNIEnv *env, jobject self, jobject am, jobject at,
 						jint sample_rate, jint buffer_size);
 	static void destroy(JNIEnv *env, jobject self);
+
+	static void setSurface(JNIEnv *env, jobject self, jint width, jint height);
 	static jint main(JNIEnv *env, jobject self, jobjectArray args);
+
 	static void pushEvent(JNIEnv *env, jobject self, jobject java_event);
-	static void setConfManInt(JNIEnv *env, jclass cls, jstring key_obj,
-								jint value);
-	static void setConfManString(JNIEnv *env, jclass cls, jstring key_obj,
-							   		jstring value_obj);
 	static void enableZoning(JNIEnv *env, jobject self, jboolean enable);
-	static void setSurfaceSize(JNIEnv *env, jobject self, jint width,
-								jint height);
 };
 
-inline bool JNI::setupSurface() {
-	JNIEnv *env = JNI::getEnv();
-
-	env->CallVoidMethod(_jobj, _MID_setupScummVMSurface);
-
-	return !env->ExceptionCheck();
-}
-
-inline void JNI::destroySurface() {
-	JNIEnv *env = JNI::getEnv();
-
-	env->CallVoidMethod(_jobj, _MID_destroyScummVMSurface);
-}
-
-inline bool JNI::swapBuffers() {
+inline int JNI::swapBuffers() {
 	JNIEnv *env = JNI::getEnv();
 
-	return env->CallBooleanMethod(_jobj, _MID_swapBuffers);
+	return env->CallIntMethod(_jobj, _MID_swapBuffers);
 }
 
 inline int JNI::writeAudio(JNIEnv *env, jbyteArray &data, int offset, int size) {
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
index ae7204f..db83303 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
@@ -1,18 +1,12 @@
 package org.inodes.gus.scummvm;
 
-import android.content.Context;
+import android.util.Log;
 import android.content.res.AssetManager;
+import android.view.SurfaceHolder;
 import android.media.AudioFormat;
 import android.media.AudioManager;
 import android.media.AudioTrack;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Process;
-import android.util.Log;
-import android.view.Surface;
-import android.view.SurfaceHolder;
 
-import javax.microedition.khronos.opengles.GL;
 import javax.microedition.khronos.opengles.GL10;
 import javax.microedition.khronos.egl.EGL10;
 import javax.microedition.khronos.egl.EGL11;
@@ -22,28 +16,242 @@ import javax.microedition.khronos.egl.EGLDisplay;
 import javax.microedition.khronos.egl.EGLSurface;
 
 import java.io.File;
-import java.util.concurrent.Semaphore;
 import java.util.Map;
 import java.util.LinkedHashMap;
 
+public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
+	final protected static String LOG_TAG = "ScummVM";
+	final private AssetManager asset_manager;
+	final private Object sem_surface;
+
+	private EGL10 egl;
+	private EGLDisplay eglDisplay = EGL10.EGL_NO_DISPLAY;
+	private EGLConfig eglConfig;
+	private EGLContext eglContext = EGL10.EGL_NO_CONTEXT;
+	private EGLSurface eglSurface = EGL10.EGL_NO_SURFACE;
+
+	private SurfaceHolder surface_holder;
+	private AudioTrack audio_track;
+	private int sample_rate = 0;
+	private int buffer_size = 0;
+
+	private String[] args;
+
+	final private native void create(AssetManager asset_manager,
+										AudioTrack audio_track,
+										int sample_rate, int buffer_size);
+	final private native void destroy();
+	final private native void setSurface(int width, int height);
+	final private native int main(String[] args);
+
+	// Set scummvm config options
+	final public native void enableZoning(boolean enable);
+	// Feed an event to ScummVM.  Safe to call from other threads.
+	final public native void pushEvent(Event e);
+
+	// Callbacks from C++ peer instance
+	abstract protected void displayMessageOnOSD(String msg);
+	abstract protected void setWindowCaption(String caption);
+	abstract protected String[] getPluginDirectories();
+	abstract protected void showVirtualKeyboard(boolean enable);
+	abstract protected String[] getSysArchives();
+
+	final protected int swapBuffers() {
+		if (!egl.eglSwapBuffers(eglDisplay, eglSurface))
+			return egl.eglGetError();
+
+		return 0;
+	}
+
+	public ScummVM(AssetManager asset_manager, SurfaceHolder holder) {
+		this.asset_manager = asset_manager;
+		sem_surface = new Object();
+
+		holder.addCallback(this);
+	}
+
+	// SurfaceHolder callback
+	final public void surfaceCreated(SurfaceHolder holder) {
+		Log.d(LOG_TAG, "surfaceCreated");
+
+		// no need to do anything, surfaceChanged() will be called in any case
+	}
+
+	// SurfaceHolder callback
+	final public void surfaceChanged(SurfaceHolder holder, int format,
+										int width, int height) {
+		Log.d(LOG_TAG, String.format("surfaceChanged: %dx%d (%d)",
+										width, height, format));
+
+		synchronized(sem_surface) {
+			surface_holder = holder;
+			sem_surface.notifyAll();
+		}
+
+		// store values for the native code
+		setSurface(width, height);
+	}
+
+	// SurfaceHolder callback
+	final public void surfaceDestroyed(SurfaceHolder holder) {
+		Log.d(LOG_TAG, "surfaceDestroyed");
+
+		synchronized(sem_surface) {
+			surface_holder = null;
+			sem_surface.notifyAll();
+		}
+
+		// clear values for the native code
+		setSurface(0, 0);
+	}
+
+	final public void setArgs(String[] args) {
+		this.args = args;
+	}
+
+	final public void run() {
+		try {
+			initAudio();
+			initEGL();
+
+			// wait for the surfaceChanged callback
+			synchronized(sem_surface) {
+				while (surface_holder == null)
+					sem_surface.wait();
+			}
+		} catch (Exception e) {
+			deinitEGL();
+			deinitAudio();
+
+			throw new RuntimeException("Error preparing the ScummVM thread", e);
+		}
+
+		create(asset_manager, audio_track, sample_rate, buffer_size);
+
+		int res = main(args);
+
+		destroy();
+
+		deinitEGL();
+		deinitAudio();
+
+		// On exit, tear everything down for a fresh restart next time.
+		System.exit(res);
+	}
+
+	public void pause() {
+		// TODO
+	}
+
+	public void resume() {
+		// TODO
+	}
+
+	final private void initEGL() throws Exception {
+		egl = (EGL10)EGLContext.getEGL();
+		eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+
+		int[] version = new int[2];
+		egl.eglInitialize(eglDisplay, version);
+
+		int[] num_config = new int[1];
+		egl.eglChooseConfig(eglDisplay, configSpec, null, 0, num_config);
+
+		final int numConfigs = num_config[0];
+
+		if (numConfigs <= 0)
+			throw new IllegalArgumentException("No configs match configSpec");
+
+		EGLConfig[] configs = new EGLConfig[numConfigs];
+		egl.eglChooseConfig(eglDisplay, configSpec, configs, numConfigs,
+							num_config);
+
+		if (false) {
+			Log.d(LOG_TAG, String.format("Found %d EGL configurations.",
+											numConfigs));
+			for (EGLConfig config : configs)
+				dumpEglConfig(config);
+		}
+
+		// Android's eglChooseConfig is busted in several versions and
+		// devices so we have to filter/rank the configs again ourselves.
+		eglConfig = chooseEglConfig(configs);
+
+		if (false) {
+			Log.d(LOG_TAG, String.format("Chose from %d EGL configs",
+											numConfigs));
+			dumpEglConfig(eglConfig);
+		}
+
+		eglContext = egl.eglCreateContext(eglDisplay, eglConfig,
+											EGL10.EGL_NO_CONTEXT, null);
+
+		if (eglContext == EGL10.EGL_NO_CONTEXT)
+			throw new Exception(String.format("Failed to create context: 0x%x",
+												egl.eglGetError()));
+	}
+
+	// Callback from C++ peer instance
+	final protected void initSurface() throws Exception {
+		eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig,
+												surface_holder, null);
+
+		if (eglSurface == EGL10.EGL_NO_SURFACE)
+			throw new Exception(String.format(
+					"eglCreateWindowSurface failed: 0x%x", egl.eglGetError()));
+
+		egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
+
+		GL10 gl = (GL10)eglContext.getGL();
+
+		Log.i(LOG_TAG, String.format("Using EGL %s (%s); GL %s/%s (%s)",
+						egl.eglQueryString(eglDisplay, EGL10.EGL_VERSION),
+						egl.eglQueryString(eglDisplay, EGL10.EGL_VENDOR),
+						gl.glGetString(GL10.GL_VERSION),
+						gl.glGetString(GL10.GL_RENDERER),
+						gl.glGetString(GL10.GL_VENDOR)));
+	}
+
+	// Callback from C++ peer instance
+	final protected void deinitSurface() {
+		if (eglDisplay != EGL10.EGL_NO_DISPLAY) {
+			egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE,
+								EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
+
+			if (eglSurface != EGL10.EGL_NO_SURFACE)
+				egl.eglDestroySurface(eglDisplay, eglSurface);
+		}
+
+		eglSurface = EGL10.EGL_NO_SURFACE;
+	}
 
-// At least in Android 2.1, eglCreateWindowSurface() requires an
-// EGLNativeWindowSurface object, which is hidden deep in the bowels
-// of libui.  Until EGL is properly exposed, it's probably safer to
-// use the Java versions of most EGL functions :(
+	final private void deinitEGL() {
+		if (eglDisplay != EGL10.EGL_NO_DISPLAY) {
+			egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE,
+								EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
 
-public class ScummVM implements SurfaceHolder.Callback {
-	protected final static String LOG_TAG = "ScummVM";
+			if (eglSurface != EGL10.EGL_NO_SURFACE)
+				egl.eglDestroySurface(eglDisplay, eglSurface);
+
+			if (eglContext != EGL10.EGL_NO_CONTEXT)
+				egl.eglDestroyContext(eglDisplay, eglContext);
+
+			egl.eglTerminate(eglDisplay);
+		}
 
-	private native void create(AssetManager am, AudioTrack audio_track,
-								int sample_rate, int buffer_size);
+		eglSurface = EGL10.EGL_NO_SURFACE;
+		eglContext = EGL10.EGL_NO_CONTEXT;
+		eglConfig = null;
+		eglDisplay = EGL10.EGL_NO_DISPLAY;
+		egl = null;
+	}
 
-	public ScummVM(Context context) throws Exception {
-		int sample_rate = AudioTrack.getNativeOutputSampleRate(
-							AudioManager.STREAM_MUSIC);
-		int buffer_size = AudioTrack.getMinBufferSize(sample_rate,
-							AudioFormat.CHANNEL_CONFIGURATION_STEREO,
-							AudioFormat.ENCODING_PCM_16BIT);
+	final private void initAudio() throws Exception {
+		sample_rate = AudioTrack.getNativeOutputSampleRate(
+									AudioManager.STREAM_MUSIC);
+		buffer_size = AudioTrack.getMinBufferSize(sample_rate,
+									AudioFormat.CHANNEL_CONFIGURATION_STEREO,
+									AudioFormat.ENCODING_PCM_16BIT);
 
 		// ~100ms
 		int buffer_size_want = (sample_rate * 2 * 2 / 10) & ~1023;
@@ -58,48 +266,28 @@ public class ScummVM implements SurfaceHolder.Callback {
 		Log.i(LOG_TAG, String.format("Using %d bytes buffer for %dHz audio",
 										buffer_size, sample_rate));
 
-		AudioTrack audio_track =
-			new AudioTrack(AudioManager.STREAM_MUSIC,
-							sample_rate,
-							AudioFormat.CHANNEL_CONFIGURATION_STEREO,
-							AudioFormat.ENCODING_PCM_16BIT,
-							buffer_size,
-							AudioTrack.MODE_STREAM);
+		audio_track = new AudioTrack(AudioManager.STREAM_MUSIC,
+									sample_rate,
+									AudioFormat.CHANNEL_CONFIGURATION_STEREO,
+									AudioFormat.ENCODING_PCM_16BIT,
+									buffer_size,
+									AudioTrack.MODE_STREAM);
 
 		if (audio_track.getState() != AudioTrack.STATE_INITIALIZED)
 			throw new Exception(
 				String.format("Error initialising AudioTrack: %d",
 								audio_track.getState()));
-
-		// Init C++ code
-		create(context.getAssets(), audio_track, sample_rate, buffer_size);
 	}
 
-	private native void nativeDestroy();
+	final private void deinitAudio() {
+		if (audio_track != null)
+			audio_track.stop();
 
-	public synchronized void destroy() {
-		nativeDestroy();
+		audio_track = null;
+		buffer_size = 0;
+		sample_rate = 0;
 	}
 
-	protected void finalize() {
-		destroy();
-	}
-
-	// Surface creation:
-	// GUI thread: create surface, release lock
-	// ScummVM thread: acquire lock (block), read surface
-
-	// Surface deletion:
-	// GUI thread: post event, acquire lock (block), return
-	// ScummVM thread: read event, free surface, release lock
-
-	// In other words, ScummVM thread does this:
-	//	acquire lock
-	//	setup surface
-	//	when SCREEN_CHANGED arrives:
-	//		destroy surface
-	//		release lock
-	//	back to acquire lock
 	static final int configSpec[] = {
 		EGL10.EGL_RED_SIZE, 5,
 		EGL10.EGL_GREEN_SIZE, 5,
@@ -109,33 +297,6 @@ public class ScummVM implements SurfaceHolder.Callback {
 		EGL10.EGL_NONE,
 	};
 
-	EGL10 egl;
-	EGLDisplay eglDisplay = EGL10.EGL_NO_DISPLAY;
-	EGLConfig eglConfig;
-	EGLContext eglContext = EGL10.EGL_NO_CONTEXT;
-	EGLSurface eglSurface = EGL10.EGL_NO_SURFACE;
-	Semaphore surfaceLock = new Semaphore(0, true);
-	SurfaceHolder nativeSurface;
-
-	public void surfaceCreated(SurfaceHolder holder) {
-		nativeSurface = holder;
-		surfaceLock.release();
-	}
-
-	public void surfaceChanged(SurfaceHolder holder, int format,
-								int width, int height) {
-		// Disabled while I debug GL problems
-		pushEvent(new Event(Event.EVENT_SCREEN_CHANGED));
-	}
-
-	public void surfaceDestroyed(SurfaceHolder holder) {
-		try {
-			surfaceLock.acquire();
-		} catch (InterruptedException e) {
-			Log.e(LOG_TAG, "Interrupted while waiting for surface lock", e);
-		}
-	}
-
 	// For debugging
 	private static final Map<String, Integer> attribs;
 
@@ -170,7 +331,7 @@ public class ScummVM implements SurfaceHolder.Callback {
 		attribs.put("TRANSPARENT_BLUE_VALUE", EGL10.EGL_TRANSPARENT_BLUE_VALUE);
 	}
 
-	private void dumpEglConfig(EGLConfig config) {
+	final private void dumpEglConfig(EGLConfig config) {
 		int[] value = new int[1];
 
 		for (Map.Entry<String, Integer> entry : attribs.entrySet()) {
@@ -184,49 +345,7 @@ public class ScummVM implements SurfaceHolder.Callback {
 		}
 	}
 
-	// Called by ScummVM thread (from initBackend)
-	private void createScummVMGLContext() {
-		egl = (EGL10)EGLContext.getEGL();
-		eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
-
-		int[] version = new int[2];
-		egl.eglInitialize(eglDisplay, version);
-
-		int[] num_config = new int[1];
-		egl.eglChooseConfig(eglDisplay, configSpec, null, 0, num_config);
-
-		final int numConfigs = num_config[0];
-
-		if (numConfigs <= 0)
-			throw new IllegalArgumentException("No configs match configSpec");
-
-		EGLConfig[] configs = new EGLConfig[numConfigs];
-		egl.eglChooseConfig(eglDisplay, configSpec, configs, numConfigs,
-							num_config);
-
-		if (false) {
-			Log.d(LOG_TAG, String.format("Found %d EGL configurations.", numConfigs));
-			for (EGLConfig config : configs)
-				dumpEglConfig(config);
-		}
-
-		// Android's eglChooseConfig is busted in several versions and
-		// devices so we have to filter/rank the configs again ourselves.
-		eglConfig = chooseEglConfig(configs);
-
-		if (false) {
-			Log.d(LOG_TAG, String.format("Chose EGL config from %d possibilities.", numConfigs));
-			dumpEglConfig(eglConfig);
-		}
-
-		eglContext = egl.eglCreateContext(eglDisplay, eglConfig,
-											EGL10.EGL_NO_CONTEXT, null);
-
-		if (eglContext == EGL10.EGL_NO_CONTEXT)
-			throw new RuntimeException("Failed to create context");
-	}
-
-	private EGLConfig chooseEglConfig(EGLConfig[] configs) {
+	final private EGLConfig chooseEglConfig(EGLConfig[] configs) {
 		int best = 0;
 		int bestScore = -1;
 		int[] value = new int[1];
@@ -286,111 +405,6 @@ public class ScummVM implements SurfaceHolder.Callback {
 		return configs[best];
 	}
 
-	// Called by ScummVM thread
-	static private boolean _log_version = true;
-
-	protected void setupScummVMSurface() {
-		try {
-			surfaceLock.acquire();
-		} catch (InterruptedException e) {
-			Log.e(LOG_TAG, "Interrupted while waiting for surface lock", e);
-			return;
-		}
-
-		eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig,
-												nativeSurface, null);
-
-		if (eglSurface == EGL10.EGL_NO_SURFACE)
-			Log.e(LOG_TAG, "CreateWindowSurface failed!");
-
-		egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
-
-		GL10 gl = (GL10)eglContext.getGL();
-
-		if (_log_version) {
-			Log.i(LOG_TAG, String.format("Using EGL %s (%s); GL %s/%s (%s)",
-											egl.eglQueryString(eglDisplay, EGL10.EGL_VERSION),
-											egl.eglQueryString(eglDisplay, EGL10.EGL_VENDOR),
-											gl.glGetString(GL10.GL_VERSION),
-											gl.glGetString(GL10.GL_RENDERER),
-											gl.glGetString(GL10.GL_VENDOR)));
-
-			// only log this once
-			_log_version = false;
-		}
-
-		int[] value = new int[1];
-		egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_WIDTH, value);
-
-		int width = value[0];
-		egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_HEIGHT, value);
-
-		int height = value[0];
-		Log.i(LOG_TAG, String.format("New surface is %dx%d", width, height));
-		setSurfaceSize(width, height);
-	}
-
-	// Called by ScummVM thread
-	protected void destroyScummVMSurface() {
-		if (eglSurface != null) {
-			egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE,
-								EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
-
-			egl.eglDestroySurface(eglDisplay, eglSurface);
-			eglSurface = EGL10.EGL_NO_SURFACE;
-		}
-
-		surfaceLock.release();
-	}
-
-	public void setSurface(SurfaceHolder holder) {
-		holder.addCallback(this);
-	}
-
-	final public boolean swapBuffers() {
-		if (!egl.eglSwapBuffers(eglDisplay, eglSurface)) {
-			int error = egl.eglGetError();
-			Log.w(LOG_TAG, String.format("eglSwapBuffers exited with error 0x%x", error));
-			if (error == EGL11.EGL_CONTEXT_LOST)
-				return false;
-		}
-
-		return true;
-	}
-
-	// Set scummvm config options
-	final public native void enableZoning(boolean enable);
-	final public native void setSurfaceSize(int width, int height);
-
-	// Feed an event to ScummVM.  Safe to call from other threads.
-	final public native void pushEvent(Event e);
-
-	// Runs the actual ScummVM program and returns when it does.
-	// This should not be called from multiple threads simultaneously...
-	final public native int scummVMMain(String[] argv);
-
-	// Callbacks from C++ peer instance
-	//protected GraphicsMode[] getSupportedGraphicsModes() {}
-	protected void displayMessageOnOSD(String msg) {}
-	protected void setWindowCaption(String caption) {}
-	protected void showVirtualKeyboard(boolean enable) {}
-	protected String[] getSysArchives() { return new String[0]; }
-	protected String[] getPluginDirectories() { return new String[0]; }
-
-	protected void initBackend() {
-		createScummVMGLContext();
-	}
-
-	public void pause() {
-		// TODO: need to pause audio
-		// TODO: need to pause engine
-	}
-
-	public void resume() {
-		// TODO: need to resume audio
-		// TODO: need to resume engine
-	}
-
 	static {
 		// For grabbing with gdb...
 		final boolean sleep_for_debugger = false;
@@ -401,10 +415,10 @@ public class ScummVM implements SurfaceHolder.Callback {
 			}
 		}
 
-		//System.loadLibrary("scummvm");
 		File cache_dir = ScummVMApplication.getLastCacheDir();
 		String libname = System.mapLibraryName("scummvm");
 		File libpath = new File(cache_dir, libname);
+
 		System.load(libpath.getPath());
 	}
 }
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
index fb6020c..92247de 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
@@ -3,6 +3,7 @@ package org.inodes.gus.scummvm;
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.content.DialogInterface;
+import android.content.res.AssetManager;
 import android.content.res.Configuration;
 import android.media.AudioManager;
 import android.os.Bundle;
@@ -14,6 +15,7 @@ import android.util.Log;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.SurfaceView;
+import android.view.SurfaceHolder;
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.inputmethod.InputMethodManager;
@@ -30,8 +32,6 @@ public class ScummVMActivity extends Activity {
 	private final static int TRACKBALL_SCALE = 2;
 
 	private class MyScummVM extends ScummVM {
-		private boolean scummvmRunning = false;
-
 		private boolean usingSmallScreen() {
 			// Multiple screen sizes came in with Android 1.6.  Have
 			// to use reflection in order to continue supporting 1.5
@@ -49,8 +49,8 @@ public class ScummVMActivity extends Activity {
 			}
 		}
 
-		public MyScummVM() throws Exception {
-			super(ScummVMActivity.this);
+		public MyScummVM(SurfaceHolder holder) {
+			super(ScummVMActivity.this.getAssets(), holder);
 
 			// Enable ScummVM zoning on 'small' screens.
 			// FIXME make this optional for the user
@@ -59,23 +59,6 @@ public class ScummVMActivity extends Activity {
 		}
 
 		@Override
-		protected void initBackend() {
-			synchronized (this) {
-				scummvmRunning = true;
-				notifyAll();
-			}
-
-			super.initBackend();
-		}
-
-		public void waitUntilRunning() throws InterruptedException {
-			synchronized (this) {
-				while (!scummvmRunning)
-					wait();
-			}
-		}
-
-		@Override
 		protected void displayMessageOnOSD(String msg) {
 			Log.i(LOG_TAG, "OSD: " + msg);
 			Toast.makeText(ScummVMActivity.this, msg, Toast.LENGTH_LONG).show();
@@ -105,6 +88,12 @@ public class ScummVMActivity extends Activity {
 					}
 				});
 		}
+
+		@Override
+		protected String[] getSysArchives() {
+			return new String[0];
+		}
+
 	}
 
 	private MyScummVM scummvm;
@@ -140,74 +129,36 @@ public class ScummVMActivity extends Activity {
 		}
 
 		SurfaceView main_surface = (SurfaceView)findViewById(R.id.main_surface);
+
 		main_surface.setOnTouchListener(new View.OnTouchListener() {
 				public boolean onTouch(View v, MotionEvent event) {
 					return onTouchEvent(event);
 				}
 			});
+
 		main_surface.setOnKeyListener(new View.OnKeyListener() {
 				public boolean onKey(View v, int code, KeyEvent ev) {
 					return onKeyDown(code, ev);
 				}
 			});
-		main_surface.requestFocus();
 
-		// Start ScummVM
-		try {
-			scummvm = new MyScummVM();
-		} catch (Exception e) {
-			Log.e(ScummVM.LOG_TAG, "Fatal error", e);
-			finish();
-			return;
-		}
-
-		scummvm_thread = new Thread(new Runnable() {
-				public void run() {
-					try {
-						runScummVM();
-					} catch (Exception e) {
-						Log.e(ScummVM.LOG_TAG, "Fatal error in ScummVM thread", e);
-						new AlertDialog.Builder(ScummVMActivity.this)
-							.setTitle("Error")
-							.setMessage(e.toString())
-							.setIcon(android.R.drawable.ic_dialog_alert)
-							.show();
-						finish();
-					}
-				}
-			}, "ScummVM");
-
-		scummvm_thread.start();
+		main_surface.requestFocus();
 
-		// Block UI thread until ScummVM has started.  In particular,
-		// this means that surface and event callbacks should be safe
-		// after this point.
-		try {
-			scummvm.waitUntilRunning();
-		} catch (InterruptedException e) {
-			Log.e(ScummVM.LOG_TAG, "Interrupted while waiting for ScummVM.initBackend", e);
-			finish();
-		}
+		getFilesDir().mkdirs();
 
-		scummvm.setSurface(main_surface.getHolder());
-	}
+		// Start ScummVM
+		scummvm = new MyScummVM(main_surface.getHolder());
 
-	// Runs in another thread
-	private void runScummVM() throws IOException {
-		getFilesDir().mkdirs();
-		String[] args = {
-			"ScummVM-lib",
+		scummvm.setArgs(new String[] {
+			"ScummVM",
 			"--config=" + getFileStreamPath("scummvmrc").getPath(),
 			"--path=" + Environment.getExternalStorageDirectory().getPath(),
 			"--gui-theme=scummmodern",
 			"--savepath=" + getDir("saves", 0).getPath()
-		};
+		});
 
-		int ret = scummvm.scummVMMain(args);
-
-		// On exit, tear everything down for a fresh
-		// restart next time.
-		System.exit(ret);
+		scummvm_thread = new Thread(scummvm, "ScummVM");
+		scummvm_thread.start();
 	}
 
 	private boolean was_paused = false;


Commit: bd7e3e9bb20dada6d40143557c473fabd373b5ed
    https://github.com/scummvm/scummvm/commit/bd7e3e9bb20dada6d40143557c473fabd373b5ed
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-03-02T14:18:34-08:00

Commit Message:
ANDROID: cleanup

Changed paths:
    backends/platform/android/android.cpp
    backends/platform/android/gfx.cpp
    backends/platform/android/texture.cpp
    backends/platform/android/texture.h



diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index 2af367e..a61f7da 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -442,9 +442,12 @@ bool OSystem_Android::pollEvent(Common::Event &event) {
 		} else {
 			// Touchscreen events need to be converted
 			// from device to game coords first.
-			const GLESTexture *tex = _show_overlay
-				? static_cast<GLESTexture *>(_overlay_texture)
-				: static_cast<GLESTexture *>(_game_texture);
+			const GLESTexture *tex;
+			if (_show_overlay)
+				tex = _overlay_texture;
+			else
+				tex = _game_texture;
+
 			event.mouse.x = scalef(event.mouse.x, tex->width(),
 									_egl_surface_width);
 			event.mouse.y = scalef(event.mouse.y, tex->height(),
diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp
index 49f3d40..7fbe896 100644
--- a/backends/platform/android/gfx.cpp
+++ b/backends/platform/android/gfx.cpp
@@ -128,8 +128,8 @@ void OSystem_Android::initSize(uint width, uint height,
 
 	_game_texture->allocBuffer(width, height);
 
-	GLuint overlay_width = _egl_surface_width;
-	GLuint overlay_height = _egl_surface_height;
+	int overlay_width = _egl_surface_width;
+	int overlay_height = _egl_surface_height;
 
 	// the 'normal' theme layout uses a max height of 400 pixels. if the
 	// surface is too big we use only a quarter of the size so that the widgets
@@ -290,13 +290,8 @@ void OSystem_Android::updateScreen() {
 
 	int res = JNI::swapBuffers();
 
-	if (res) {
+	if (res)
 		warning("swapBuffers returned 0x%x", res);
-#if 0
-		JNI::initSurface();
-		setupSurface();
-#endif
-	}
 }
 
 Graphics::Surface *OSystem_Android::lockScreen() {
diff --git a/backends/platform/android/texture.cpp b/backends/platform/android/texture.cpp
index c5cba97..9840e7d 100644
--- a/backends/platform/android/texture.cpp
+++ b/backends/platform/android/texture.cpp
@@ -154,7 +154,7 @@ void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h,
 	GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
 	GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
 
-	setDirtyRect(Common::Rect(x, y, x+w, y+h));
+	setDirtyRect(Common::Rect(x, y, x + w, y + h));
 
 	if (static_cast<int>(w) * bytesPerPixel() == pitch) {
 		GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h,
diff --git a/backends/platform/android/texture.h b/backends/platform/android/texture.h
index 050eafa..1227462 100644
--- a/backends/platform/android/texture.h
+++ b/backends/platform/android/texture.h
@@ -59,10 +59,6 @@ public:
 		return _surface.h;
 	}
 
-	inline GLuint texture_name() const {
-		return _texture_name;
-	}
-
 	inline const Graphics::Surface *surface_const() const {
 		return &_surface;
 	}


Commit: 82a9beff2b52b2dd3eb7368dd46d8d50cb9f2d9f
    https://github.com/scummvm/scummvm/commit/82a9beff2b52b2dd3eb7368dd46d8d50cb9f2d9f
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-03-02T14:18:34-08:00

Commit Message:
ANDROID: Move swapBuffers to the native side

Changed paths:
    backends/platform/android/gfx.cpp
    backends/platform/android/jni.cpp
    backends/platform/android/jni.h
    backends/platform/android/org/inodes/gus/scummvm/ScummVM.java



diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp
index 7fbe896..96ba5e7 100644
--- a/backends/platform/android/gfx.cpp
+++ b/backends/platform/android/gfx.cpp
@@ -288,10 +288,8 @@ void OSystem_Android::updateScreen() {
 
 	GLCALL(glPopMatrix());
 
-	int res = JNI::swapBuffers();
-
-	if (res)
-		warning("swapBuffers returned 0x%x", res);
+	if (!JNI::swapBuffers())
+		LOGW("swapBuffers failed: 0x%x", glGetError());
 }
 
 Graphics::Surface *OSystem_Android::lockScreen() {
diff --git a/backends/platform/android/jni.cpp b/backends/platform/android/jni.cpp
index 28a03d0..3c2324d 100644
--- a/backends/platform/android/jni.cpp
+++ b/backends/platform/android/jni.cpp
@@ -40,6 +40,9 @@ jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
 JavaVM *JNI::_vm = 0;
 jobject JNI::_jobj = 0;
 jobject JNI::_jobj_audio_track = 0;
+jobject JNI::_jobj_egl = 0;
+jobject JNI::_jobj_egl_display = 0;
+jobject JNI::_jobj_egl_surface = 0;
 
 Common::Archive *JNI::_asset_archive = 0;
 OSystem_Android *JNI::_system = 0;
@@ -63,10 +66,11 @@ jmethodID JNI::_MID_setWindowCaption = 0;
 jmethodID JNI::_MID_showVirtualKeyboard = 0;
 jmethodID JNI::_MID_getSysArchives = 0;
 jmethodID JNI::_MID_getPluginDirectories = 0;
-jmethodID JNI::_MID_swapBuffers = 0;
 jmethodID JNI::_MID_initSurface = 0;
 jmethodID JNI::_MID_deinitSurface = 0;
 
+jmethodID JNI::_MID_EGL10_eglSwapBuffers = 0;
+
 jmethodID JNI::_MID_AudioTrack_flush = 0;
 jmethodID JNI::_MID_AudioTrack_pause = 0;
 jmethodID JNI::_MID_AudioTrack_play = 0;
@@ -75,6 +79,8 @@ jmethodID JNI::_MID_AudioTrack_write = 0;
 
 const JNINativeMethod JNI::_natives[] = {
 	{ "create", "(Landroid/content/res/AssetManager;"
+				"Ljavax/microedition/khronos/egl/EGL10;"
+				"Ljavax/microedition/khronos/egl/EGLDisplay;"
 				"Landroid/media/AudioTrack;II)V",
 		(void *)JNI::create },
 	{ "destroy", "()V",
@@ -318,17 +324,23 @@ void JNI::getPluginDirectories(Common::FSList &dirs) {
 	}
 }
 
-void JNI::initSurface() {
+bool JNI::initSurface() {
 	JNIEnv *env = JNI::getEnv();
 
-	env->CallVoidMethod(_jobj, _MID_initSurface);
+	jobject obj = env->CallObjectMethod(_jobj, _MID_initSurface);
 
-	if (env->ExceptionCheck()) {
+	if (!obj || env->ExceptionCheck()) {
 		LOGE("initSurface failed");
 
 		env->ExceptionDescribe();
 		env->ExceptionClear();
+
+		return false;
 	}
+
+	_jobj_egl_surface = env->NewGlobalRef(obj);
+
+	return true;
 }
 
 void JNI::deinitSurface() {
@@ -342,6 +354,9 @@ void JNI::deinitSurface() {
 		env->ExceptionDescribe();
 		env->ExceptionClear();
 	}
+
+	env->DeleteGlobalRef(_jobj_egl_surface);
+	_jobj_egl_surface = 0;
 }
 
 void JNI::setAudioPause() {
@@ -394,11 +409,12 @@ void JNI::setAudioStop() {
 
 // natives for the dark side
 
-void JNI::create(JNIEnv *env, jobject self, jobject am, jobject at,
-					jint audio_sample_rate, jint audio_buffer_size) {
+void JNI::create(JNIEnv *env, jobject self, jobject asset_manager,
+				jobject egl, jobject egl_display,
+				jobject at, jint audio_sample_rate, jint audio_buffer_size) {
 	assert(!_system);
 
-	_asset_archive = new AndroidAssetArchive(am);
+	_asset_archive = new AndroidAssetArchive(asset_manager);
 	assert(_asset_archive);
 
 	_system = new OSystem_Android(audio_sample_rate, audio_buffer_size);
@@ -407,6 +423,7 @@ void JNI::create(JNIEnv *env, jobject self, jobject am, jobject at,
 	// weak global ref to allow class to be unloaded
 	// ... except dalvik implements NewWeakGlobalRef only on froyo
 	//_jobj = env->NewWeakGlobalRef(self);
+
 	_jobj = env->NewGlobalRef(self);
 
 	jclass cls = env->GetObjectClass(_jobj);
@@ -422,12 +439,28 @@ void JNI::create(JNIEnv *env, jobject self, jobject am, jobject at,
 	FIND_METHOD(showVirtualKeyboard, "(Z)V");
 	FIND_METHOD(getSysArchives, "()[Ljava/lang/String;");
 	FIND_METHOD(getPluginDirectories, "()[Ljava/lang/String;");
-	FIND_METHOD(swapBuffers, "()I");
-	FIND_METHOD(initSurface, "()V");
+	FIND_METHOD(initSurface, "()Ljavax/microedition/khronos/egl/EGLSurface;");
 	FIND_METHOD(deinitSurface, "()V");
 
 #undef FIND_METHOD
 
+	_jobj_egl = env->NewGlobalRef(egl);
+	_jobj_egl_display = env->NewGlobalRef(egl_display);
+
+	cls = env->GetObjectClass(_jobj_egl);
+
+#define FIND_METHOD(name, signature) do {									\
+		_MID_EGL10_ ## name = env->GetMethodID(cls, #name, signature);		\
+		if (_MID_EGL10_ ## name == 0)										\
+			return;															\
+	} while (0)
+
+	FIND_METHOD(eglSwapBuffers, "(Ljavax/microedition/khronos/egl/EGLDisplay;"
+								"Ljavax/microedition/khronos/egl/EGLSurface;"
+								")Z");
+
+#undef FIND_METHOD
+
 	_jobj_audio_track = env->NewGlobalRef(at);
 
 	cls = env->GetObjectClass(_jobj_audio_track);
@@ -459,6 +492,9 @@ void JNI::destroy(JNIEnv *env, jobject self) {
 
 	// see above
 	//JNI::getEnv()->DeleteWeakGlobalRef(_jobj);
+
+	JNI::getEnv()->DeleteGlobalRef(_jobj_egl_display);
+	JNI::getEnv()->DeleteGlobalRef(_jobj_egl);
 	JNI::getEnv()->DeleteGlobalRef(_jobj_audio_track);
 	JNI::getEnv()->DeleteGlobalRef(_jobj);
 }
diff --git a/backends/platform/android/jni.h b/backends/platform/android/jni.h
index 0005136..2a1405d 100644
--- a/backends/platform/android/jni.h
+++ b/backends/platform/android/jni.h
@@ -60,8 +60,8 @@ public:
 	static void showVirtualKeyboard(bool enable);
 	static void addSysArchivesToSearchSet(Common::SearchSet &s, int priority);
 
-	static inline int swapBuffers();
-	static void initSurface();
+	static inline bool swapBuffers();
+	static bool initSurface();
 	static void deinitSurface();
 
 	static void setAudioPause();
@@ -76,6 +76,9 @@ private:
 	// back pointer to (java) peer instance
 	static jobject _jobj;
 	static jobject _jobj_audio_track;
+	static jobject _jobj_egl;
+	static jobject _jobj_egl_display;
+	static jobject _jobj_egl_surface;
 
 	static Common::Archive *_asset_archive;
 	static OSystem_Android *_system;
@@ -97,10 +100,11 @@ private:
 	static jmethodID _MID_showVirtualKeyboard;
 	static jmethodID _MID_getSysArchives;
 	static jmethodID _MID_getPluginDirectories;
-	static jmethodID _MID_swapBuffers;
 	static jmethodID _MID_initSurface;
 	static jmethodID _MID_deinitSurface;
 
+	static jmethodID _MID_EGL10_eglSwapBuffers;
+
 	static jmethodID _MID_AudioTrack_flush;
 	static jmethodID _MID_AudioTrack_pause;
 	static jmethodID _MID_AudioTrack_play;
@@ -113,8 +117,10 @@ private:
 	static void throwRuntimeException(JNIEnv *env, const char *msg);
 
 	// natives for the dark side
-	static void create(JNIEnv *env, jobject self, jobject am, jobject at,
-						jint sample_rate, jint buffer_size);
+	static void create(JNIEnv *env, jobject self, jobject asset_manager,
+						jobject egl, jobject egl_display,
+						jobject at, jint audio_sample_rate,
+						jint audio_buffer_size);
 	static void destroy(JNIEnv *env, jobject self);
 
 	static void setSurface(JNIEnv *env, jobject self, jint width, jint height);
@@ -124,10 +130,11 @@ private:
 	static void enableZoning(JNIEnv *env, jobject self, jboolean enable);
 };
 
-inline int JNI::swapBuffers() {
+inline bool JNI::swapBuffers() {
 	JNIEnv *env = JNI::getEnv();
 
-	return env->CallIntMethod(_jobj, _MID_swapBuffers);
+	return env->CallBooleanMethod(_jobj_egl, _MID_EGL10_eglSwapBuffers,
+									_jobj_egl_display, _jobj_egl_surface);
 }
 
 inline int JNI::writeAudio(JNIEnv *env, jbyteArray &data, int offset, int size) {
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
index db83303..75407c6 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
@@ -38,6 +38,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
 	private String[] args;
 
 	final private native void create(AssetManager asset_manager,
+										EGL10 egl, EGLDisplay eglDisplay,
 										AudioTrack audio_track,
 										int sample_rate, int buffer_size);
 	final private native void destroy();
@@ -56,13 +57,6 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
 	abstract protected void showVirtualKeyboard(boolean enable);
 	abstract protected String[] getSysArchives();
 
-	final protected int swapBuffers() {
-		if (!egl.eglSwapBuffers(eglDisplay, eglSurface))
-			return egl.eglGetError();
-
-		return 0;
-	}
-
 	public ScummVM(AssetManager asset_manager, SurfaceHolder holder) {
 		this.asset_manager = asset_manager;
 		sem_surface = new Object();
@@ -126,7 +120,8 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
 			throw new RuntimeException("Error preparing the ScummVM thread", e);
 		}
 
-		create(asset_manager, audio_track, sample_rate, buffer_size);
+		create(asset_manager, egl, eglDisplay,
+				audio_track, sample_rate, buffer_size);
 
 		int res = main(args);
 
@@ -192,7 +187,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
 	}
 
 	// Callback from C++ peer instance
-	final protected void initSurface() throws Exception {
+	final protected EGLSurface initSurface() throws Exception {
 		eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig,
 												surface_holder, null);
 
@@ -210,6 +205,8 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
 						gl.glGetString(GL10.GL_VERSION),
 						gl.glGetString(GL10.GL_RENDERER),
 						gl.glGetString(GL10.GL_VENDOR)));
+
+		return eglSurface;
 	}
 
 	// Callback from C++ peer instance


Commit: d6e838e1b38a568869ffd655a9bebd225593ffad
    https://github.com/scummvm/scummvm/commit/d6e838e1b38a568869ffd655a9bebd225593ffad
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-03-02T14:18:35-08:00

Commit Message:
ANDROID: Merge FIND_METHODs

Changed paths:
    backends/platform/android/jni.cpp



diff --git a/backends/platform/android/jni.cpp b/backends/platform/android/jni.cpp
index 3c2324d..7fe23d0 100644
--- a/backends/platform/android/jni.cpp
+++ b/backends/platform/android/jni.cpp
@@ -428,54 +428,38 @@ void JNI::create(JNIEnv *env, jobject self, jobject asset_manager,
 
 	jclass cls = env->GetObjectClass(_jobj);
 
-#define FIND_METHOD(name, signature) do {							\
-		_MID_ ## name = env->GetMethodID(cls, #name, signature);	\
-		if (_MID_ ## name == 0)										\
-			return;													\
+#define FIND_METHOD(prefix, name, signature) do {							\
+		_MID_ ## prefix ## name = env->GetMethodID(cls, #name, signature);	\
+		if (_MID_ ## prefix ## name == 0)									\
+			return;															\
 	} while (0)
 
-	FIND_METHOD(setWindowCaption, "(Ljava/lang/String;)V");
-	FIND_METHOD(displayMessageOnOSD, "(Ljava/lang/String;)V");
-	FIND_METHOD(showVirtualKeyboard, "(Z)V");
-	FIND_METHOD(getSysArchives, "()[Ljava/lang/String;");
-	FIND_METHOD(getPluginDirectories, "()[Ljava/lang/String;");
-	FIND_METHOD(initSurface, "()Ljavax/microedition/khronos/egl/EGLSurface;");
-	FIND_METHOD(deinitSurface, "()V");
-
-#undef FIND_METHOD
+	FIND_METHOD(, setWindowCaption, "(Ljava/lang/String;)V");
+	FIND_METHOD(, displayMessageOnOSD, "(Ljava/lang/String;)V");
+	FIND_METHOD(, showVirtualKeyboard, "(Z)V");
+	FIND_METHOD(, getSysArchives, "()[Ljava/lang/String;");
+	FIND_METHOD(, getPluginDirectories, "()[Ljava/lang/String;");
+	FIND_METHOD(, initSurface, "()Ljavax/microedition/khronos/egl/EGLSurface;");
+	FIND_METHOD(, deinitSurface, "()V");
 
 	_jobj_egl = env->NewGlobalRef(egl);
 	_jobj_egl_display = env->NewGlobalRef(egl_display);
 
 	cls = env->GetObjectClass(_jobj_egl);
 
-#define FIND_METHOD(name, signature) do {									\
-		_MID_EGL10_ ## name = env->GetMethodID(cls, #name, signature);		\
-		if (_MID_EGL10_ ## name == 0)										\
-			return;															\
-	} while (0)
-
-	FIND_METHOD(eglSwapBuffers, "(Ljavax/microedition/khronos/egl/EGLDisplay;"
-								"Ljavax/microedition/khronos/egl/EGLSurface;"
-								")Z");
-
-#undef FIND_METHOD
+	FIND_METHOD(EGL10_, eglSwapBuffers,
+				"(Ljavax/microedition/khronos/egl/EGLDisplay;"
+				"Ljavax/microedition/khronos/egl/EGLSurface;)Z");
 
 	_jobj_audio_track = env->NewGlobalRef(at);
 
 	cls = env->GetObjectClass(_jobj_audio_track);
 
-#define FIND_METHOD(name, signature) do {									\
-		_MID_AudioTrack_ ## name = env->GetMethodID(cls, #name, signature);	\
-		if (_MID_AudioTrack_ ## name == 0)									\
-			return;															\
-	} while (0)
-
-	FIND_METHOD(flush, "()V");
-	FIND_METHOD(pause, "()V");
-	FIND_METHOD(play, "()V");
-	FIND_METHOD(stop, "()V");
-	FIND_METHOD(write, "([BII)I");
+	FIND_METHOD(AudioTrack_, flush, "()V");
+	FIND_METHOD(AudioTrack_, pause, "()V");
+	FIND_METHOD(AudioTrack_, play, "()V");
+	FIND_METHOD(AudioTrack_, stop, "()V");
+	FIND_METHOD(AudioTrack_, write, "([BII)I");
 
 #undef FIND_METHOD
 


Commit: ccfe427eb542235070e8576b4cc47217d92046fd
    https://github.com/scummvm/scummvm/commit/ccfe427eb542235070e8576b4cc47217d92046fd
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-03-02T14:18:35-08:00

Commit Message:
ANDROID: Check for a surface in updateScreen()

Changed paths:
    backends/platform/android/android.cpp
    backends/platform/android/gfx.cpp
    backends/platform/android/jni.h



diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index a61f7da..484f688 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -400,8 +400,6 @@ bool OSystem_Android::pollEvent(Common::Event &event) {
 
 			_screen_changeid = JNI::surface_changeid;
 			JNI::deinitSurface();
-
-			// TODO prevent swapBuffers
 		}
 	}
 
diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp
index 96ba5e7..15e517a 100644
--- a/backends/platform/android/gfx.cpp
+++ b/backends/platform/android/gfx.cpp
@@ -198,6 +198,9 @@ void OSystem_Android::updateScreen() {
 
 	GLTHREADCHECK;
 
+	if (!JNI::haveSurface())
+		return;
+
 	if (!_force_redraw &&
 			!_game_texture->dirty() &&
 			!_overlay_texture->dirty() &&
diff --git a/backends/platform/android/jni.h b/backends/platform/android/jni.h
index 2a1405d..d2bc89e 100644
--- a/backends/platform/android/jni.h
+++ b/backends/platform/android/jni.h
@@ -60,6 +60,7 @@ public:
 	static void showVirtualKeyboard(bool enable);
 	static void addSysArchivesToSearchSet(Common::SearchSet &s, int priority);
 
+	static inline bool haveSurface();
 	static inline bool swapBuffers();
 	static bool initSurface();
 	static void deinitSurface();
@@ -130,6 +131,10 @@ private:
 	static void enableZoning(JNIEnv *env, jobject self, jboolean enable);
 };
 
+inline bool JNI::haveSurface() {
+	return _jobj_egl_surface != 0;
+}
+
 inline bool JNI::swapBuffers() {
 	JNIEnv *env = JNI::getEnv();
 


Commit: 25ef065a4172443eebdd1031c8a387f30f930ec4
    https://github.com/scummvm/scummvm/commit/25ef065a4172443eebdd1031c8a387f30f930ec4
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-03-02T14:18:35-08:00

Commit Message:
ANDROID: Implement pause/resume

Don't just kill the whole process when the Activity is stopped. Instead,
use its events to pause or resume audio and the running engine (if any).
Of course not every engines implements that... but at least an incoming
call doesn't kill the game now (lol).

Changed paths:
    backends/platform/android/jni.cpp
    backends/platform/android/jni.h
    backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
    backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java



diff --git a/backends/platform/android/jni.cpp b/backends/platform/android/jni.cpp
index 7fe23d0..1e28b06 100644
--- a/backends/platform/android/jni.cpp
+++ b/backends/platform/android/jni.cpp
@@ -27,6 +27,7 @@
 
 #include "base/main.h"
 #include "common/config-manager.h"
+#include "engines/engine.h"
 
 #include "backends/platform/android/android.h"
 #include "backends/platform/android/asset-archive.h"
@@ -93,6 +94,8 @@ const JNINativeMethod JNI::_natives[] = {
 		(void *)JNI::pushEvent },
 	{ "enableZoning", "(Z)V",
 		(void *)JNI::enableZoning },
+	{ "pauseEngine", "(Z)V",
+		(void *)JNI::pauseEngine }
 };
 
 JNI::JNI() {
@@ -613,5 +616,15 @@ void JNI::enableZoning(JNIEnv *env, jobject self, jboolean enable) {
 	_system->enableZoning(enable);
 }
 
+void JNI::pauseEngine(JNIEnv *env, jobject self, jboolean pause) {
+	if (!_system || !g_engine)
+		return;
+
+	if ((pause && !g_engine->isPaused()) || (!pause && g_engine->isPaused())) {
+		LOGD("pauseEngine: %d", pause);
+		g_engine->pauseEngine(pause);
+	}
+}
+
 #endif
 
diff --git a/backends/platform/android/jni.h b/backends/platform/android/jni.h
index d2bc89e..7eb1079 100644
--- a/backends/platform/android/jni.h
+++ b/backends/platform/android/jni.h
@@ -129,6 +129,8 @@ private:
 
 	static void pushEvent(JNIEnv *env, jobject self, jobject java_event);
 	static void enableZoning(JNIEnv *env, jobject self, jboolean enable);
+
+	static void pauseEngine(JNIEnv *env, jobject self, jboolean pause);
 };
 
 inline bool JNI::haveSurface() {
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
index 75407c6..ffb0109 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
@@ -44,6 +44,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
 	final private native void destroy();
 	final private native void setSurface(int width, int height);
 	final private native int main(String[] args);
+	final private native void pauseEngine(boolean pause);
 
 	// Set scummvm config options
 	final public native void enableZoning(boolean enable);
@@ -134,12 +135,14 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
 		System.exit(res);
 	}
 
-	public void pause() {
-		// TODO
-	}
+	public void pause(boolean pause) {
+		if (audio_track != null && !pause)
+			audio_track.play();
+
+		pauseEngine(pause);
 
-	public void resume() {
-		// TODO
+		if (audio_track != null && pause)
+			audio_track.stop();
 	}
 
 	final private void initEGL() throws Exception {
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
index 92247de..22ccaf0 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
@@ -161,30 +161,46 @@ public class ScummVMActivity extends Activity {
 		scummvm_thread.start();
 	}
 
-	private boolean was_paused = false;
-
 	@Override
-	public void onPause() {
-		if (scummvm != null) {
-			was_paused = true;
-			scummvm.pause();
-		}
+	public void onStart() {
+		Log.d(ScummVM.LOG_TAG, "onStart");
 
-		super.onPause();
+		super.onStart();
 	}
 
 	@Override
 	public void onResume() {
+		Log.d(ScummVM.LOG_TAG, "onResume");
+
 		super.onResume();
 
-		if (scummvm != null && was_paused)
-			scummvm.resume();
+		if (scummvm != null)
+			scummvm.pause(false);
+	}
+
+	@Override
+	public void onPause() {
+		Log.d(ScummVM.LOG_TAG, "onPause");
+
+		super.onPause();
 
-		was_paused = false;
+		if (scummvm != null)
+			scummvm.pause(true);
 	}
 
 	@Override
 	public void onStop() {
+		Log.d(ScummVM.LOG_TAG, "onStop");
+
+		super.onStop();
+	}
+
+	@Override
+	public void onDestroy() {
+		Log.d(ScummVM.LOG_TAG, "onDestroy");
+
+		super.onDestroy();
+
 		if (scummvm != null) {
 			scummvm.pushEvent(new Event(Event.EVENT_QUIT));
 
@@ -194,9 +210,9 @@ public class ScummVMActivity extends Activity {
 			} catch (InterruptedException e) {
 				Log.i(ScummVM.LOG_TAG, "Error while joining ScummVM thread", e);
 			}
-		}
 
-		super.onStop();
+			scummvm = null;
+		}
 	}
 
 	static final int MSG_MENU_LONG_PRESS = 1;


Commit: c2d4cce429baa56b5a0962a854ece6163270995f
    https://github.com/scummvm/scummvm/commit/c2d4cce429baa56b5a0962a854ece6163270995f
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-03-02T14:18:35-08:00

Commit Message:
ANDROID: On pause, put all threads in a coma

Since not every engine respects pauseEngine(), or they're in a state
where it simply gets ignored, put all threads in a group coma. Without
this, code still kept looping and wasting cpu cycles, while the user
might want to do use her/his droid for something else.

Changed paths:
    backends/platform/android/android.cpp
    backends/platform/android/jni.cpp
    backends/platform/android/jni.h



diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index 484f688..d4a2253 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -151,6 +151,12 @@ void *OSystem_Android::timerThreadFunc(void *arg) {
 	tv.tv_nsec = 100 * 1000 * 1000;	// 100ms
 
 	while (!system->_timer_thread_exit) {
+		if (JNI::pause) {
+			LOGD("timer thread going to sleep");
+			sem_wait(&JNI::pause_sem);
+			LOGD("timer thread woke up");
+		}
+			
 		timer->handler();
 		nanosleep(&tv, 0);
 	}
@@ -192,6 +198,12 @@ void *OSystem_Android::audioThreadFunc(void *arg) {
 	uint silence_count = 33;
 
 	while (!system->_audio_thread_exit) {
+		if (JNI::pause) {
+			LOGD("audio thread going to sleep");
+			sem_wait(&JNI::pause_sem);
+			LOGD("audio thread woke up");
+		}
+			
 		buf = (byte *)env->GetPrimitiveArrayCritical(bufa, 0);
 		assert(buf);
 
@@ -401,6 +413,19 @@ bool OSystem_Android::pollEvent(Common::Event &event) {
 			_screen_changeid = JNI::surface_changeid;
 			JNI::deinitSurface();
 		}
+
+		if (JNI::pause) {
+			// release some resources
+			// TODO
+			// free textures? they're garbled anyway since no engine
+			// respects EVENT_SCREEN_CHANGED
+			LOGD("deinitialiting surface");
+			JNI::deinitSurface();
+
+			LOGD("main thread going to sleep");
+			sem_wait(&JNI::pause_sem);
+			LOGD("main thread woke up");
+		}
 	}
 
 	lockMutex(_event_queue_lock);
diff --git a/backends/platform/android/jni.cpp b/backends/platform/android/jni.cpp
index 1e28b06..9ecd957 100644
--- a/backends/platform/android/jni.cpp
+++ b/backends/platform/android/jni.cpp
@@ -48,6 +48,9 @@ jobject JNI::_jobj_egl_surface = 0;
 Common::Archive *JNI::_asset_archive = 0;
 OSystem_Android *JNI::_system = 0;
 
+bool JNI::pause = false;
+sem_t JNI::pause_sem = { 0 };
+
 int JNI::surface_changeid = 0;
 int JNI::egl_surface_width = 0;
 int JNI::egl_surface_height = 0;
@@ -417,6 +420,10 @@ void JNI::create(JNIEnv *env, jobject self, jobject asset_manager,
 				jobject at, jint audio_sample_rate, jint audio_buffer_size) {
 	assert(!_system);
 
+	pause = false;
+	// initial value of zero!
+	sem_init(&pause_sem, 0, 0);
+
 	_asset_archive = new AndroidAssetArchive(asset_manager);
 	assert(_asset_archive);
 
@@ -477,6 +484,8 @@ void JNI::destroy(JNIEnv *env, jobject self) {
 	g_system = 0;
 	_system = 0;
 
+	sem_destroy(&pause_sem);
+
 	// see above
 	//JNI::getEnv()->DeleteWeakGlobalRef(_jobj);
 
@@ -616,13 +625,23 @@ void JNI::enableZoning(JNIEnv *env, jobject self, jboolean enable) {
 	_system->enableZoning(enable);
 }
 
-void JNI::pauseEngine(JNIEnv *env, jobject self, jboolean pause) {
-	if (!_system || !g_engine)
+void JNI::pauseEngine(JNIEnv *env, jobject self, jboolean value) {
+	if (!_system)
 		return;
 
-	if ((pause && !g_engine->isPaused()) || (!pause && g_engine->isPaused())) {
-		LOGD("pauseEngine: %d", pause);
-		g_engine->pauseEngine(pause);
+	if (g_engine)
+		if ((value && !g_engine->isPaused()) ||
+				(!value && g_engine->isPaused())) {
+			LOGD("pauseEngine: %d", value);
+			g_engine->pauseEngine(value);
+		}
+
+	pause = value;
+
+	if (!pause) {
+		// wake up all threads
+		for (uint i = 0; i < 3; ++i)
+			sem_post(&pause_sem);
 	}
 }
 
diff --git a/backends/platform/android/jni.h b/backends/platform/android/jni.h
index 7eb1079..569a3dd 100644
--- a/backends/platform/android/jni.h
+++ b/backends/platform/android/jni.h
@@ -29,6 +29,7 @@
 #if defined(__ANDROID__)
 
 #include <jni.h>
+#include <semaphore.h>
 
 #include "common/fs.h"
 #include "common/archive.h"
@@ -41,6 +42,9 @@ private:
 	virtual ~JNI();
 
 public:
+	static bool pause;
+	static sem_t pause_sem;
+
 	static int surface_changeid;
 	static int egl_surface_width;
 	static int egl_surface_height;


Commit: 2d4a64d18493b142b1899a822202015339733cfa
    https://github.com/scummvm/scummvm/commit/2d4a64d18493b142b1899a822202015339733cfa
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-03-02T14:18:36-08:00

Commit Message:
ANDROID: Properly release texture resources

When calling glDeleteTextures() we need a valid surface.

Changed paths:
    backends/platform/android/android.cpp
    backends/platform/android/gfx.cpp
    backends/platform/android/texture.cpp
    backends/platform/android/texture.h



diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index d4a2253..491e5fb 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -124,10 +124,6 @@ OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) :
 OSystem_Android::~OSystem_Android() {
 	ENTER();
 
-	delete _game_texture;
-	delete _overlay_texture;
-	delete _mouse_texture;
-
 	delete _savefile;
 	delete _timer;
 	delete _mixer;
@@ -323,6 +319,10 @@ void OSystem_Android::initBackend() {
 
 	setupSurface();
 
+	_game_texture = new GLESPaletteTexture();
+	_overlay_texture = new GLES4444Texture();
+	_mouse_texture = new GLESPaletteATexture();
+
 	// renice this thread to boost the audio thread
 	if (setpriority(PRIO_PROCESS, 0, 19) < 0)
 		warning("couldn't renice the main thread");
@@ -400,9 +400,17 @@ bool OSystem_Android::pollEvent(Common::Event &event) {
 			if (JNI::egl_surface_width > 0 && JNI::egl_surface_height > 0) {
 				LOGD("initializing surface");
 
+				_game_texture->release();
+				_overlay_texture->release();
+				_mouse_texture->release();
+
 				JNI::deinitSurface();
 				setupSurface();
 
+				_game_texture->reinit();
+				_overlay_texture->reinit();
+				_mouse_texture->reinit();
+
 				event.type = Common::EVENT_SCREEN_CHANGED;
 
 				return true;
@@ -410,15 +418,20 @@ bool OSystem_Android::pollEvent(Common::Event &event) {
 
 			LOGD("deinitialiting surface");
 
+			_game_texture->release();
+			_overlay_texture->release();
+			_mouse_texture->release();
+
 			_screen_changeid = JNI::surface_changeid;
 			JNI::deinitSurface();
 		}
 
 		if (JNI::pause) {
 			// release some resources
-			// TODO
-			// free textures? they're garbled anyway since no engine
-			// respects EVENT_SCREEN_CHANGED
+			_game_texture->release();
+			_overlay_texture->release();
+			_mouse_texture->release();
+
 			LOGD("deinitialiting surface");
 			JNI::deinitSurface();
 
@@ -573,6 +586,10 @@ void OSystem_Android::quit() {
 	_timer_thread_exit = true;
 	pthread_join(_timer_thread, 0);
 
+	delete _game_texture;
+	delete _overlay_texture;
+	delete _mouse_texture;
+
 	JNI::deinitSurface();
 }
 
diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp
index 15e517a..e2cc854 100644
--- a/backends/platform/android/gfx.cpp
+++ b/backends/platform/android/gfx.cpp
@@ -94,21 +94,6 @@ void OSystem_Android::setupSurface() {
 
 	GLCALL(glEnable(GL_TEXTURE_2D));
 
-	if (!_game_texture)
-		_game_texture = new GLESPaletteTexture();
-	else
-		_game_texture->reinitGL();
-
-	if (!_overlay_texture)
-		_overlay_texture = new GLES4444Texture();
-	else
-		_overlay_texture->reinitGL();
-
-	if (!_mouse_texture)
-		_mouse_texture = new GLESPaletteATexture();
-	else
-		_mouse_texture->reinitGL();
-
 	GLCALL(glViewport(0, 0, _egl_surface_width, _egl_surface_height));
 
 	GLCALL(glMatrixMode(GL_PROJECTION));
diff --git a/backends/platform/android/texture.cpp b/backends/platform/android/texture.cpp
index 9840e7d..ea8a89d 100644
--- a/backends/platform/android/texture.cpp
+++ b/backends/platform/android/texture.cpp
@@ -98,12 +98,15 @@ GLESTexture::GLESTexture() :
 }
 
 GLESTexture::~GLESTexture() {
+	release();
+}
+
+void GLESTexture::release() {
 	debug("Destroying texture %u", _texture_name);
 	GLCALL(glDeleteTextures(1, &_texture_name));
 }
 
-void GLESTexture::reinitGL() {
-	GLCALL(glDeleteTextures(1, &_texture_name));
+void GLESTexture::reinit() {
 	GLCALL(glGenTextures(1, &_texture_name));
 
 	// bypass allocBuffer() shortcut to reinit the texture properly
diff --git a/backends/platform/android/texture.h b/backends/platform/android/texture.h
index 1227462..f1d5cad 100644
--- a/backends/platform/android/texture.h
+++ b/backends/platform/android/texture.h
@@ -42,7 +42,9 @@ public:
 	GLESTexture();
 	virtual ~GLESTexture();
 
-	virtual void reinitGL();
+	void release();
+	void reinit();
+
 	virtual void allocBuffer(GLuint width, GLuint height);
 
 	virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,






More information about the Scummvm-git-logs mailing list