Drop direct use of (private) libEGL.so and call EGL functions via Java.

This removes the final private library - we should be completely above
board now.

svn-id: r50677
This commit is contained in:
Angus Lees 2010-07-05 13:06:58 +00:00
parent d4ad7b8a6d
commit 330e94feed
4 changed files with 116 additions and 125 deletions

View file

@ -2,9 +2,8 @@ Building the ScummVM Android port
=================================
You will need these things to build:
1. Android EGL headers and library
2. Android SDK
3. An arm-oe-linux-androideabi GCC toolchain(*)
1. Android SDK
2. An arm-oe-linux-androideabi GCC toolchain(*)
In the example commands, we are going to build against the Android 1.5
native ABI (but using the Android 1.6 SDK tools). Other version
@ -18,21 +17,13 @@ you have some other prefix variation.
In detail:
1. Android EGL headers and library
1. Android SDK
You can build these from the full Android source, but it is far easier
to just download the 3 Android EGL headers from here:
http://android.git.kernel.org/?p=platform/frameworks/base.git;a=tree;f=opengl/include/EGL;hb=HEAD
(copy them to a directory called "EGL" somewhere)
Download the SDK from http://developer.android.com/ and install
somewhere. You will need both the API level 8 (aka Android 2.2) and
API level 3 (aka Android 1.5) platforms.
... and grab libEGL.so off an existing phone/emulator:
adb pull /system/lib/libEGL.so /tmp
2. Android SDK
Download and install somewhere.
3. arm-*-linux-androideabi GCC toolchain
2. arm-*-linux-androideabi GCC toolchain
You have several choices for toolchains:
@ -95,11 +86,6 @@ Then build ScummVM:
export ANDROID_TOP=<root of built Android source>
EGL_INC="-I<location of EGL/ header directory>"
EGL_LIBS="-L<location of libEGL.so>"
CPPFLAGS="$EGL_INC" \
LDFLAGS="-g $EGL_LIBS" \
./configure --backend=android --host=android --enable-zlib #and any other flags
make scummvm.apk

View file

@ -41,7 +41,6 @@
#include <GLES/gl.h>
#include <GLES/glext.h>
#include <EGL/egl.h>
#include <android/log.h>
#include "common/archive.h"
@ -166,12 +165,11 @@ private:
jmethodID MID_getPluginDirectories;
jmethodID MID_setupScummVMSurface;
jmethodID MID_destroyScummVMSurface;
jmethodID MID_swapBuffers;
int _screen_changeid;
EGLDisplay _egl_display;
EGLSurface _egl_surface;
EGLint _egl_surface_width;
EGLint _egl_surface_height;
int _egl_surface_width;
int _egl_surface_height;
bool _force_redraw;
@ -223,6 +221,10 @@ 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);
@ -303,8 +305,6 @@ public:
OSystem_Android::OSystem_Android(jobject am)
: _back_ptr(0),
_egl_display(EGL_NO_DISPLAY),
_egl_surface(EGL_NO_SURFACE),
_screen_changeid(0),
_force_redraw(false),
_game_texture(NULL),
@ -369,6 +369,7 @@ bool OSystem_Android::initJavaHooks(JNIEnv* env, jobject self) {
FIND_METHOD(getPluginDirectories, "()[Ljava/lang/String;");
FIND_METHOD(setupScummVMSurface, "()V");
FIND_METHOD(destroyScummVMSurface, "()V");
FIND_METHOD(swapBuffers, "()Z");
#undef FIND_METHOD
@ -581,6 +582,7 @@ int OSystem_Android::getGraphicsMode() const {
}
void OSystem_Android::setupScummVMSurface() {
ENTER("setupScummVMSurface");
JNIEnv* env = JNU_GetEnv();
env->CallVoidMethod(_back_ptr, MID_setupScummVMSurface);
if (env->ExceptionCheck())
@ -588,37 +590,8 @@ void OSystem_Android::setupScummVMSurface() {
// EGL set up with a new surface. Initialise OpenGLES context.
_egl_display = eglGetCurrentDisplay();
_egl_surface = eglGetCurrentSurface(EGL_DRAW);
static bool log_version = true;
if (log_version) {
__android_log_print(ANDROID_LOG_INFO, LOG_TAG,
"Using EGL %s (%s); GL %s/%s (%s)",
eglQueryString(_egl_display, EGL_VERSION),
eglQueryString(_egl_display, EGL_VENDOR),
glGetString(GL_VERSION),
glGetString(GL_RENDERER),
glGetString(GL_VENDOR));
log_version = false; // only log this once
}
GLESTexture::initGLExtensions();
if (!eglQuerySurface(_egl_display, _egl_surface,
EGL_WIDTH, &_egl_surface_width) ||
!eglQuerySurface(_egl_display, _egl_surface,
EGL_HEIGHT, &_egl_surface_height)) {
JNU_ThrowByName(env, "java/lang/RuntimeException",
"Error fetching EGL surface width/height");
return;
}
__android_log_print(ANDROID_LOG_INFO, LOG_TAG,
"New surface is %dx%d",
_egl_surface_width, _egl_surface_height);
CHECK_GL_ERROR();
// Turn off anything that looks like 3D ;)
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
@ -664,7 +637,6 @@ void OSystem_Android::setupScummVMSurface() {
}
void OSystem_Android::destroyScummVMSurface() {
_egl_surface = EGL_NO_SURFACE;
JNIEnv* env = JNU_GetEnv();
env->CallVoidMethod(_back_ptr, MID_destroyScummVMSurface);
// Can't use OpenGLES functions after this
@ -745,8 +717,11 @@ void OSystem_Android::updateScreen() {
glPushMatrix();
if (_shake_offset != 0) {
// This is the only case where _game_texture doesn't
if (_shake_offset != 0 ||
(!_focus_rect.isEmpty() &&
!Common::Rect(_game_texture->width(),
_game_texture->height()).contains(_focus_rect))) {
// These are the only cases where _game_texture doesn't
// cover the entire screen.
glClearColorx(0, 0, 0, 1 << 16);
glClear(GL_COLOR_BUFFER_BIT);
@ -759,16 +734,6 @@ void OSystem_Android::updateScreen() {
_game_texture->drawTexture(0, 0,
_egl_surface_width, _egl_surface_height);
} else {
// Need to ensure any exposed out-of-bounds region doesn't go
// all hall-of-mirrors. If _shake_offset != 0, we've already
// done this above.
const Common::Rect
screen_bounds(_game_texture->width(), _game_texture->height());
if (!screen_bounds.contains(_focus_rect) && _shake_offset != 0) {
glClearColorx(0, 0, 0, 1 << 16);
glClear(GL_COLOR_BUFFER_BIT);
}
glPushMatrix();
glScalex(xdiv(_egl_surface_width, _focus_rect.width()),
xdiv(_egl_surface_height, _focus_rect.height()),
@ -831,16 +796,13 @@ void OSystem_Android::updateScreen() {
CHECK_GL_ERROR();
if (!eglSwapBuffers(_egl_display, _egl_surface)) {
EGLint error = eglGetError();
warning("eglSwapBuffers exited with error 0x%x", error);
// Some errors mean we need to reinit GL
if (error == EGL_CONTEXT_LOST) {
JNIEnv* env = JNU_GetEnv();
if (!env->CallBooleanMethod(_back_ptr, MID_swapBuffers)) {
// Context lost -> need to reinit GL
destroyScummVMSurface();
setupScummVMSurface();
}
}
}
Graphics::Surface *OSystem_Android::lockScreen() {
ENTER("lockScreen()");
@ -1365,6 +1327,12 @@ static void ScummVM_enableZoning(JNIEnv* env, jobject self, jboolean enable) {
cpp_obj->enableZoning(enable);
}
static void ScummVM_setSurfaceSize(JNIEnv* env, jobject self,
jint width, jint height) {
OSystem_Android* cpp_obj = OSystem_Android::fromJavaObject(env, self);
cpp_obj->setSurfaceSize(width, height);
}
const static JNINativeMethod gMethods[] = {
{ "create", "(Landroid/content/res/AssetManager;)V",
(void*)ScummVM_create },
@ -1381,6 +1349,8 @@ const static JNINativeMethod gMethods[] = {
(void*)ScummVM_setConfManString },
{ "enableZoning", "(Z)V",
(void*)ScummVM_enableZoning },
{ "setSurfaceSize", "(II)V",
(void*)ScummVM_setSurfaceSize },
};
JNIEXPORT jint JNICALL

View file

@ -12,7 +12,10 @@ 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;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
@ -129,6 +132,7 @@ public class ScummVM implements SurfaceHolder.Callback {
}
// Called by ScummVM thread
static private boolean _log_version = true;
protected void setupScummVMSurface() {
try {
surfaceLock.acquire();
@ -140,6 +144,26 @@ public class ScummVM implements SurfaceHolder.Callback {
eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig,
nativeSurface, null);
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)));
_log_version = false; // only log this once
}
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
@ -158,11 +182,22 @@ public class ScummVM implements SurfaceHolder.Callback {
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 static void loadConfigFile(String path);
final public native static void setConfMan(String key, int value);
final public native static void setConfMan(String key, String value);
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);

2
configure vendored
View file

@ -2515,7 +2515,7 @@ case $_backend in
# -lgcc is carefully placed here - we want to catch
# all toolchain symbols in *our* libraries rather
# than pick up anything unhygenic from the Android libs.
LIBS="-Wl,-Bstatic $static_libs -Wl,-Bdynamic -lgcc $system_libs -lstdc++ -llog -lGLESv1_CM -lEGL"
LIBS="-Wl,-Bstatic $static_libs -Wl,-Bdynamic -lgcc $system_libs -lstdc++ -llog -lGLESv1_CM"
DEFINES="$DEFINES -D__ANDROID__ -DANDROID_BACKEND -DREDUCE_MEMORY_USAGE"
add_line_to_config_mk 'PLUGIN_LDFLAGS += $(LDFLAGS) -Wl,-shared,-Bsymbolic'