From b77feb4f21ae6c5f8378ad755adb702465e60c88 Mon Sep 17 00:00:00 2001 From: kimxilxyong Date: Sun, 12 Jun 2011 09:26:22 +0000 Subject: [PATCH] Android: Added proper OpenGL ES version detection and a best EGL Config Chooser git-svn-id: http://jmonkeyengine.googlecode.com/svn/trunk@7594 75d07b2b-3a1a-0410-a2c5-0572b91ccdca --- engine/src/android/com/jme3/R.java | 20 -- .../src/android/com/jme3/app/AndroidHarness.java | 4 +- .../com/jme3/app/android/AndroidApplication.java | 4 +- .../com/jme3/system/android/OGLESContext.java | 212 +++++++++++++++++++-- .../android/jme3test/android/AndroidActivity.java | 2 +- 5 files changed, 201 insertions(+), 41 deletions(-) delete mode 100644 engine/src/android/com/jme3/R.java diff --git a/engine/src/android/com/jme3/R.java b/engine/src/android/com/jme3/R.java deleted file mode 100644 index af9687431..000000000 --- a/engine/src/android/com/jme3/R.java +++ /dev/null @@ -1,20 +0,0 @@ -/* AUTO-GENERATED FILE. DO NOT MODIFY. - * - * This class was automatically generated by the - * aapt tool from the resource data it found. It - * should not be modified by hand. - */ - -package com.jme3; - -public final class R { - public static final class attr { - } - public static final class layout { - public static final int main=0x7f020000; - } - public static final class string { - public static final int app_name=0x7f030000; - public static final int jme3_appclass=0x7f030001; - } -} diff --git a/engine/src/android/com/jme3/app/AndroidHarness.java b/engine/src/android/com/jme3/app/AndroidHarness.java index 9b88c15ff..5fb82f389 100644 --- a/engine/src/android/com/jme3/app/AndroidHarness.java +++ b/engine/src/android/com/jme3/app/AndroidHarness.java @@ -136,7 +136,7 @@ public class AndroidHarness extends Activity implements DialogInterface.OnClickL final String sTrace = s; - logger.severe(t != null ? t.toString() : "Failed"); + logger.severe(t != null ? t.toString() : "OpenGL Exception"); logger.severe((errorMsg != null ? errorMsg + ": " : "") + sTrace); this.runOnUiThread(new Runnable() { @@ -145,7 +145,7 @@ public class AndroidHarness extends Activity implements DialogInterface.OnClickL { AlertDialog dialog = new AlertDialog.Builder(AndroidHarness.this) // .setIcon(R.drawable.alert_dialog_icon) - .setTitle(t != null ? t.toString() : "Failed") + .setTitle(t != null ? (t.getMessage() != null ? (t.getMessage() + ": " + t.getClass().getName()) : t.getClass().getName()) : "OpenGL Exception") .setPositiveButton("Kill", AndroidHarness.this) .setMessage((errorMsg != null ? errorMsg + ": " : "") + sTrace) .create(); diff --git a/engine/src/android/com/jme3/app/android/AndroidApplication.java b/engine/src/android/com/jme3/app/android/AndroidApplication.java index c2e99e1ff..5d6ed2c75 100644 --- a/engine/src/android/com/jme3/app/android/AndroidApplication.java +++ b/engine/src/android/com/jme3/app/android/AndroidApplication.java @@ -266,10 +266,10 @@ public abstract class AndroidApplication extends Application implements DialogIn activity.runOnUiThread(new Runnable() { @Override public void run() - { + { AlertDialog dialog = new AlertDialog.Builder(activity) // .setIcon(R.drawable.alert_dialog_icon) - .setTitle(t != null ? t.toString() : "Failed") + .setTitle(t != null ? (t.getMessage() != null ? (t.getMessage() + ": " + t.getClass().getName()) : t.getClass().getName()) : "Exception") .setPositiveButton("Kill", AndroidApplication.this) .setMessage((errorMsg != null ? errorMsg + ": " : "") + sTrace) .create(); diff --git a/engine/src/android/com/jme3/system/android/OGLESContext.java b/engine/src/android/com/jme3/system/android/OGLESContext.java index e3b3200f4..88a0e3f5c 100644 --- a/engine/src/android/com/jme3/system/android/OGLESContext.java +++ b/engine/src/android/com/jme3/system/android/OGLESContext.java @@ -34,6 +34,7 @@ package com.jme3.system.android; import android.app.Activity; import android.content.Context; +import android.opengl.GLES20; import android.opengl.GLSurfaceView; import android.view.SurfaceHolder; @@ -52,7 +53,11 @@ import com.jme3.system.SystemListener; import com.jme3.system.Timer; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Logger; + +import javax.microedition.khronos.egl.EGL10; import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.egl.EGLContext; +import javax.microedition.khronos.egl.EGLDisplay; import javax.microedition.khronos.opengles.GL10; @@ -84,7 +89,12 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer protected int frameRate = 33; //protected int minFrameDuration = 1000 / frameRate; // Set a max FPS of 33 protected int minFrameDuration = 0; // No FPS cap - + + /** + * EGL_RENDERABLE_TYPE: EGL_OPENGL_ES_BIT = OpenGL ES 1.0 | EGL_OPENGL_ES2_BIT = OpenGL ES 2.0 + */ + protected int clientOpenGLESVersion = 1; + public OGLESContext() { } @Override @@ -104,7 +114,7 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer } /** * createView - * @param AndroidInput The Android input which must be bound to an activity + * @param view The Android input which will be used as the GLSurfaceView for this context * @return GLSurfaceView The newly created view */ public GLSurfaceView createView(AndroidInput view) @@ -114,30 +124,190 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer /** * createView - * @param AndroidInput The Android input which must be bound to an activity + * @param view The Android input which will be used as the GLSurfaceView for this context * @param debugflags 0, GLSurfaceView.DEBUG_CHECK_GL_ERROR | GLSurfaceView.DEBUG_LOG_GL_CALLS * @return GLSurfaceView The newly created view */ public GLSurfaceView createView(AndroidInput view, int debugflags) - { + { + EGL10 egl = (EGL10) EGLContext.getEGL(); + EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); + + int[] version = new int[2]; + if (egl.eglInitialize(display, version) == true) + { + logger.info("Display EGL Version: " + version[0] + "." + version[1]); + } + + //Querying number of configurations + int[] num_conf = new int[1]; + egl.eglGetConfigs(display, null, 0, num_conf); //if configuration array is null it still returns the number of configurations + int configurations = num_conf[0]; + + //Querying actual configurations + EGLConfig[] conf = new EGLConfig[configurations]; + egl.eglGetConfigs(display, conf, configurations, num_conf); + + EGLConfig bestConfig = null; + int[] value = new int[1]; + int EGL_OPENGL_ES2_BIT = 4; + + // Loop over all configs to get the best + for(int i = 0; i < configurations; i++) + { + //logger.info("Supported EGL Configuration #" + i ); + + if (conf[i] != null) + { + //logger.info(String.format("conf[%d] = %s", i, conf[i].toString() ) ); + //logEGLConfig(conf[i], display, egl); + egl.eglGetConfigAttrib(display, conf[i], EGL10.EGL_RENDERABLE_TYPE, value); + if ((value[0] & EGL_OPENGL_ES2_BIT) != 0) + { + clientOpenGLESVersion = 2; // OpenGL ES 2.0 detected + } + + bestConfig = better(bestConfig, conf[i], egl, display); + } + else + { + break; + } + } + + if (clientOpenGLESVersion < 2) + { + logger.severe("OpenGL ES 2.0 is not supported on this device"); + } + + logger.info("JME3 using best EGL configuration available here: "); + logEGLConfig(bestConfig, display, egl); + + // Finished querying the configs + + + // Start to set up the view this.view = view; - /* - * Requesting client version from GLSurfaceView which is extended by - * AndroidInput. - * This is required to get OpenGL ES 2.0 - */ - view.setEGLContextClientVersion(2); - + /* + * Requesting client version from GLSurfaceView which is extended by + * AndroidInput. + */ + view.setEGLContextClientVersion(clientOpenGLESVersion); + //RGB565, Depth16 - view.setEGLConfigChooser(5, 6, 5, 0, 16, 0); + //view.setEGLConfigChooser(5, 6, 5, 0, 16, 0); + + // Choose best config + egl.eglGetConfigAttrib(display, bestConfig, EGL10.EGL_RED_SIZE, value); + int redSize = value[0]; + + egl.eglGetConfigAttrib(display, bestConfig, EGL10.EGL_GREEN_SIZE, value); + int greenSize = value[0]; + + egl.eglGetConfigAttrib(display, bestConfig, EGL10.EGL_BLUE_SIZE, value); + int blueSize = value[0]; + + egl.eglGetConfigAttrib(display, bestConfig, EGL10.EGL_ALPHA_SIZE, value); + int alphaSize = value[0]; + + egl.eglGetConfigAttrib(display, bestConfig, EGL10.EGL_DEPTH_SIZE, value); + int depthSize = value[0]; + + egl.eglGetConfigAttrib(display, bestConfig, EGL10.EGL_STENCIL_SIZE, value); + int stencilSize = value[0]; + + view.setEGLConfigChooser(redSize, greenSize, blueSize, alphaSize, depthSize, stencilSize); + view.setFocusableInTouchMode(true); view.setFocusable(true); view.getHolder().setType(SurfaceHolder.SURFACE_TYPE_GPU); - view.setDebugFlags(debugflags); - view.setRenderer(this); +// view.setDebugFlags(GLSurfaceView.DEBUG_CHECK_GL_ERROR); +// | GLSurfaceView.DEBUG_LOG_GL_CALLS); + view.setRenderer(this); return view; + } + + /** + * Returns the best of the two EGLConfig passed according to depth and colours + * @param a The first candidate + * @param b The second candidate + * @return The chosen candidate + */ + private EGLConfig better(EGLConfig a, EGLConfig b, EGL10 egl, EGLDisplay display) + { + if(a == null) return b; + + EGLConfig result = null; + + int[] value = new int[1]; + + egl.eglGetConfigAttrib(display, a, EGL10.EGL_DEPTH_SIZE, value); + int depthA = value[0]; + + egl.eglGetConfigAttrib(display, b, EGL10.EGL_DEPTH_SIZE, value); + int depthB = value[0]; + + if(depthA > depthB) + result = a; + else if(depthA < depthB) + result = b; + else //if depthA == depthB + { + egl.eglGetConfigAttrib(display, a, EGL10.EGL_RED_SIZE, value); + int redA = value[0]; + + egl.eglGetConfigAttrib(display, b, EGL10.EGL_RED_SIZE, value); + int redB = value[0]; + + if(redA > redB) + result = a; + else if(redA < redB) + result = b; + else //if redA == redB + { + // Don't care + result = a; + } + } + return result; + } + + /** + * log output with egl config details + * @param conf + * @param display + * @param egl + */ + private void logEGLConfig(EGLConfig conf, EGLDisplay display, EGL10 egl) + { + int[] value = new int[1]; + + egl.eglGetConfigAttrib(display, conf, EGL10.EGL_RED_SIZE, value); + logger.info(String.format("EGL_RED_SIZE = %d", value[0] ) ); + + egl.eglGetConfigAttrib(display, conf, EGL10.EGL_BLUE_SIZE, value); + logger.info(String.format("EGL_BLUE_SIZE = %d", value[0] ) ); + + egl.eglGetConfigAttrib(display, conf, EGL10.EGL_GREEN_SIZE, value); + logger.info(String.format("EGL_GREEN_SIZE = %d", value[0] ) ); + + egl.eglGetConfigAttrib(display, conf, EGL10.EGL_ALPHA_SIZE, value); + logger.info(String.format("EGL_ALPHA_SIZE = %d", value[0] ) ); + + egl.eglGetConfigAttrib(display, conf, EGL10.EGL_DEPTH_SIZE, value); + logger.info(String.format("EGL_DEPTH_SIZE = %d", value[0] ) ); + + egl.eglGetConfigAttrib(display, conf, EGL10.EGL_STENCIL_SIZE, value); + logger.info(String.format("EGL_STENCIL_SIZE = %d", value[0] ) ); + + egl.eglGetConfigAttrib(display, conf, EGL10.EGL_RENDERABLE_TYPE, value); + logger.info(String.format("EGL_RENDERABLE_TYPE = %d", value[0] ) ); + + + } + protected void initInThread() @@ -152,7 +322,7 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer { Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread thread, Throwable thrown) { - ((AndroidHarness)ctx).handleError("Uncaught exception thrown in "+thread.toString(), thrown); + ((AndroidHarness)ctx).handleError("Exception thrown in " + thread.toString(), thrown); } }); } @@ -160,11 +330,16 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer { Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread thread, Throwable thrown) { - listener.handleError("Uncaught exception thrown in "+thread.toString(), thrown); + listener.handleError("Exception thrown in " + thread.toString(), thrown); } }); } + if (clientOpenGLESVersion < 2) + { + throw new UnsupportedOperationException("OpenGL ES 2.0 is not supported on this device"); + } + timer = new AndroidTimer(); renderer = new OGLESShaderRenderer(); @@ -278,6 +453,7 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer @Override public void onSurfaceCreated(GL10 gl, EGLConfig cfg) { + if (created.get() && renderer != null) { renderer.resetGLObjects(); @@ -394,5 +570,9 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer } } + public int getClientOpenGLESVersion() + { + return clientOpenGLESVersion; + } } diff --git a/engine/src/android/jme3test/android/AndroidActivity.java b/engine/src/android/jme3test/android/AndroidActivity.java index 350d3c202..6f116f48d 100644 --- a/engine/src/android/jme3test/android/AndroidActivity.java +++ b/engine/src/android/jme3test/android/AndroidActivity.java @@ -15,7 +15,7 @@ import android.opengl.GLSurfaceView; import android.os.Bundle; import android.view.Window; import android.view.WindowManager; -import com.jme3.R; + import com.jme3.system.AppSettings; import com.jme3.system.JmeSystem; import com.jme3.system.android.OGLESContext; -- 2.11.0