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;