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

View file

@ -41,7 +41,6 @@
#include <GLES/gl.h> #include <GLES/gl.h>
#include <GLES/glext.h> #include <GLES/glext.h>
#include <EGL/egl.h>
#include <android/log.h> #include <android/log.h>
#include "common/archive.h" #include "common/archive.h"
@ -166,12 +165,11 @@ private:
jmethodID MID_getPluginDirectories; jmethodID MID_getPluginDirectories;
jmethodID MID_setupScummVMSurface; jmethodID MID_setupScummVMSurface;
jmethodID MID_destroyScummVMSurface; jmethodID MID_destroyScummVMSurface;
jmethodID MID_swapBuffers;
int _screen_changeid; int _screen_changeid;
EGLDisplay _egl_display; int _egl_surface_width;
EGLSurface _egl_surface; int _egl_surface_height;
EGLint _egl_surface_width;
EGLint _egl_surface_height;
bool _force_redraw; bool _force_redraw;
@ -223,6 +221,10 @@ public:
virtual void initBackend(); virtual void initBackend();
void addPluginDirectories(Common::FSList &dirs) const; void addPluginDirectories(Common::FSList &dirs) const;
void enableZoning(bool enable) { _enable_zoning = enable; } 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 bool hasFeature(Feature f);
virtual void setFeatureState(Feature f, bool enable); virtual void setFeatureState(Feature f, bool enable);
@ -303,8 +305,6 @@ public:
OSystem_Android::OSystem_Android(jobject am) OSystem_Android::OSystem_Android(jobject am)
: _back_ptr(0), : _back_ptr(0),
_egl_display(EGL_NO_DISPLAY),
_egl_surface(EGL_NO_SURFACE),
_screen_changeid(0), _screen_changeid(0),
_force_redraw(false), _force_redraw(false),
_game_texture(NULL), _game_texture(NULL),
@ -369,6 +369,7 @@ bool OSystem_Android::initJavaHooks(JNIEnv* env, jobject self) {
FIND_METHOD(getPluginDirectories, "()[Ljava/lang/String;"); FIND_METHOD(getPluginDirectories, "()[Ljava/lang/String;");
FIND_METHOD(setupScummVMSurface, "()V"); FIND_METHOD(setupScummVMSurface, "()V");
FIND_METHOD(destroyScummVMSurface, "()V"); FIND_METHOD(destroyScummVMSurface, "()V");
FIND_METHOD(swapBuffers, "()Z");
#undef FIND_METHOD #undef FIND_METHOD
@ -581,6 +582,7 @@ int OSystem_Android::getGraphicsMode() const {
} }
void OSystem_Android::setupScummVMSurface() { void OSystem_Android::setupScummVMSurface() {
ENTER("setupScummVMSurface");
JNIEnv* env = JNU_GetEnv(); JNIEnv* env = JNU_GetEnv();
env->CallVoidMethod(_back_ptr, MID_setupScummVMSurface); env->CallVoidMethod(_back_ptr, MID_setupScummVMSurface);
if (env->ExceptionCheck()) if (env->ExceptionCheck())
@ -588,37 +590,8 @@ void OSystem_Android::setupScummVMSurface() {
// EGL set up with a new surface. Initialise OpenGLES context. // 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(); 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 ;) // Turn off anything that looks like 3D ;)
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
@ -664,7 +637,6 @@ void OSystem_Android::setupScummVMSurface() {
} }
void OSystem_Android::destroyScummVMSurface() { void OSystem_Android::destroyScummVMSurface() {
_egl_surface = EGL_NO_SURFACE;
JNIEnv* env = JNU_GetEnv(); JNIEnv* env = JNU_GetEnv();
env->CallVoidMethod(_back_ptr, MID_destroyScummVMSurface); env->CallVoidMethod(_back_ptr, MID_destroyScummVMSurface);
// Can't use OpenGLES functions after this // Can't use OpenGLES functions after this
@ -745,8 +717,11 @@ void OSystem_Android::updateScreen() {
glPushMatrix(); glPushMatrix();
if (_shake_offset != 0) { if (_shake_offset != 0 ||
// This is the only case where _game_texture doesn't (!_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. // cover the entire screen.
glClearColorx(0, 0, 0, 1 << 16); glClearColorx(0, 0, 0, 1 << 16);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
@ -759,16 +734,6 @@ void OSystem_Android::updateScreen() {
_game_texture->drawTexture(0, 0, _game_texture->drawTexture(0, 0,
_egl_surface_width, _egl_surface_height); _egl_surface_width, _egl_surface_height);
} else { } 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(); glPushMatrix();
glScalex(xdiv(_egl_surface_width, _focus_rect.width()), glScalex(xdiv(_egl_surface_width, _focus_rect.width()),
xdiv(_egl_surface_height, _focus_rect.height()), xdiv(_egl_surface_height, _focus_rect.height()),
@ -831,16 +796,13 @@ void OSystem_Android::updateScreen() {
CHECK_GL_ERROR(); CHECK_GL_ERROR();
if (!eglSwapBuffers(_egl_display, _egl_surface)) { JNIEnv* env = JNU_GetEnv();
EGLint error = eglGetError(); if (!env->CallBooleanMethod(_back_ptr, MID_swapBuffers)) {
warning("eglSwapBuffers exited with error 0x%x", error); // Context lost -> need to reinit GL
// Some errors mean we need to reinit GL
if (error == EGL_CONTEXT_LOST) {
destroyScummVMSurface(); destroyScummVMSurface();
setupScummVMSurface(); setupScummVMSurface();
} }
} }
}
Graphics::Surface *OSystem_Android::lockScreen() { Graphics::Surface *OSystem_Android::lockScreen() {
ENTER("lockScreen()"); ENTER("lockScreen()");
@ -1365,6 +1327,12 @@ static void ScummVM_enableZoning(JNIEnv* env, jobject self, jboolean enable) {
cpp_obj->enableZoning(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[] = { const static JNINativeMethod gMethods[] = {
{ "create", "(Landroid/content/res/AssetManager;)V", { "create", "(Landroid/content/res/AssetManager;)V",
(void*)ScummVM_create }, (void*)ScummVM_create },
@ -1381,6 +1349,8 @@ const static JNINativeMethod gMethods[] = {
(void*)ScummVM_setConfManString }, (void*)ScummVM_setConfManString },
{ "enableZoning", "(Z)V", { "enableZoning", "(Z)V",
(void*)ScummVM_enableZoning }, (void*)ScummVM_enableZoning },
{ "setSurfaceSize", "(II)V",
(void*)ScummVM_setSurfaceSize },
}; };
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL

View file

@ -12,7 +12,10 @@ import android.util.Log;
import android.view.Surface; import android.view.Surface;
import android.view.SurfaceHolder; 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.EGL10;
import javax.microedition.khronos.egl.EGL11;
import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext; import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay; import javax.microedition.khronos.egl.EGLDisplay;
@ -129,6 +132,7 @@ public class ScummVM implements SurfaceHolder.Callback {
} }
// Called by ScummVM thread // Called by ScummVM thread
static private boolean _log_version = true;
protected void setupScummVMSurface() { protected void setupScummVMSurface() {
try { try {
surfaceLock.acquire(); surfaceLock.acquire();
@ -140,6 +144,26 @@ public class ScummVM implements SurfaceHolder.Callback {
eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig, eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig,
nativeSurface, null); nativeSurface, null);
egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); 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 // Called by ScummVM thread
@ -158,11 +182,22 @@ public class ScummVM implements SurfaceHolder.Callback {
holder.addCallback(this); 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 // Set scummvm config options
final public native static void loadConfigFile(String path); 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, int value);
final public native static void setConfMan(String key, String value); final public native static void setConfMan(String key, String value);
final public native void enableZoning(boolean enable); 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. // Feed an event to ScummVM. Safe to call from other threads.
final public native void pushEvent(Event e); 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 # -lgcc is carefully placed here - we want to catch
# all toolchain symbols in *our* libraries rather # all toolchain symbols in *our* libraries rather
# than pick up anything unhygenic from the Android libs. # 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" DEFINES="$DEFINES -D__ANDROID__ -DANDROID_BACKEND -DREDUCE_MEMORY_USAGE"
add_line_to_config_mk 'PLUGIN_LDFLAGS += $(LDFLAGS) -Wl,-shared,-Bsymbolic' add_line_to_config_mk 'PLUGIN_LDFLAGS += $(LDFLAGS) -Wl,-shared,-Bsymbolic'