From 33db5460c347bdb3568d458dd4654d469248b716 Mon Sep 17 00:00:00 2001 From: "iwg..ic" Date: Sun, 3 Nov 2013 03:24:14 +0000 Subject: [PATCH] Android: Update Android Config Chooser to the same level as r10798 from trunk. Fixes issues due to finding the EGL config too early based on a default display instead of finding the config when asked for it by the surface. see post: http://hub.jmonkeyengine.org/forum/topic/crash-nexus-10-android-4-3/ see post: http://hub.jmonkeyengine.org/forum/topic/failure-starting-any-jme-app-on-device/ git-svn-id: https://jmonkeyengine.googlecode.com/svn/branches/3.0final@10868 75d07b2b-3a1a-0410-a2c5-0572b91ccdca --- .../jme3/renderer/android/RendererUtil.java | 102 +++++++++-- .../system/android/AndroidConfigChooser.java | 172 +++++++++--------- .../com/jme3/system/android/OGLESContext.java | 116 ++++++------ 3 files changed, 227 insertions(+), 163 deletions(-) diff --git a/engine/src/android/com/jme3/renderer/android/RendererUtil.java b/engine/src/android/com/jme3/renderer/android/RendererUtil.java index a84ca1775..ce611044d 100644 --- a/engine/src/android/com/jme3/renderer/android/RendererUtil.java +++ b/engine/src/android/com/jme3/renderer/android/RendererUtil.java @@ -3,23 +3,27 @@ package com.jme3.renderer.android; import android.opengl.GLES20; import android.opengl.GLU; import com.jme3.renderer.RendererException; +import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.egl.EGL11; /** - * Utility class used by the {@link OGLESShaderRenderer renderer} and sister classes. - * + * Utility class used by the {@link OGLESShaderRenderer renderer} and sister + * classes. + * * @author Kirill Vainer */ public class RendererUtil { - + /** - * When set to true, every OpenGL call will check for errors and throw - * an exception if there is one, if false, no error checking is performed. + * When set to true, every OpenGL call will check for errors and throw an + * exception if there is one, if false, no error checking is performed. */ public static boolean ENABLE_ERROR_CHECKING = true; - + /** - * Checks for an OpenGL error and throws a {@link RendererException} - * if there is one. Ignores the value of {@link RendererUtil#ENABLE_ERROR_CHECKING}. + * Checks for an OpenGL error and throws a {@link RendererException} if + * there is one. Ignores the value of + * {@link RendererUtil#ENABLE_ERROR_CHECKING}. */ public static void checkGLErrorForced() { int error = GLES20.glGetError(); @@ -32,14 +36,86 @@ public class RendererUtil { } } } - + + /** + * Checks for an EGL error and throws a {@link RendererException} if there + * is one. Ignores the value of {@link RendererUtil#ENABLE_ERROR_CHECKING}. + */ + public static void checkEGLError(EGL10 egl) { + int error = egl.eglGetError(); + if (error != EGL10.EGL_SUCCESS) { + String errorMessage; + switch (error) { + case EGL10.EGL_SUCCESS: + return; + case EGL10.EGL_NOT_INITIALIZED: + errorMessage = "EGL is not initialized, or could not be " + + "initialized, for the specified EGL display connection. "; + break; + case EGL10.EGL_BAD_ACCESS: + errorMessage = "EGL cannot access a requested resource " + + "(for example a context is bound in another thread). "; + break; + case EGL10.EGL_BAD_ALLOC: + errorMessage = "EGL failed to allocate resources for the requested operation."; + break; + case EGL10.EGL_BAD_ATTRIBUTE: + errorMessage = "An unrecognized attribute or attribute " + + "value was passed in the attribute list. "; + break; + case EGL10.EGL_BAD_CONTEXT: + errorMessage = "An EGLContext argument does not name a valid EGL rendering context. "; + break; + case EGL10.EGL_BAD_CONFIG: + errorMessage = "An EGLConfig argument does not name a valid EGL frame buffer configuration. "; + break; + case EGL10.EGL_BAD_CURRENT_SURFACE: + errorMessage = "The current surface of the calling thread " + + "is a window, pixel buffer or pixmap that is no longer valid. "; + break; + case EGL10.EGL_BAD_DISPLAY: + errorMessage = "An EGLDisplay argument does not name a valid EGL display connection. "; + break; + case EGL10.EGL_BAD_SURFACE: + errorMessage = "An EGLSurface argument does not name a " + + "valid surface (window, pixel buffer or pixmap) configured for GL rendering. "; + break; + case EGL10.EGL_BAD_MATCH: + errorMessage = "Arguments are inconsistent (for example, a " + + "valid context requires buffers not supplied by a valid surface). "; + break; + case EGL10.EGL_BAD_PARAMETER: + errorMessage = "One or more argument values are invalid."; + break; + case EGL10.EGL_BAD_NATIVE_PIXMAP: + errorMessage = "A NativePixmapType argument does not refer to a valid native pixmap. "; + break; + case EGL10.EGL_BAD_NATIVE_WINDOW: + errorMessage = "A NativeWindowType argument does not refer to a valid native window. "; + break; + case EGL11.EGL_CONTEXT_LOST: + errorMessage = "A power management event has occurred. " + + "The application must destroy all contexts and reinitialise " + + "OpenGL ES state and objects to continue rendering. "; + break; + default: + errorMessage = "Unknown"; + } + + throw new RendererException("EGL error 0x" + Integer.toHexString(error) + ": " + errorMessage); + } + } + /** - * Checks for an OpenGL error and throws a {@link RendererException} - * if there is one. Does nothing if {@link RendererUtil#ENABLE_ERROR_CHECKING} - * is set to false. + * Checks for an OpenGL error and throws a {@link RendererException} if + * there is one. Does nothing if {@link RendererUtil#ENABLE_ERROR_CHECKING} + * is set to + * false. */ public static void checkGLError() { - if (!ENABLE_ERROR_CHECKING) return; + if (!ENABLE_ERROR_CHECKING) { + return; + } int error = GLES20.glGetError(); if (error != 0) { String message = GLU.gluErrorString(error); diff --git a/engine/src/android/com/jme3/system/android/AndroidConfigChooser.java b/engine/src/android/com/jme3/system/android/AndroidConfigChooser.java index 9eead12fa..b3036203d 100644 --- a/engine/src/android/com/jme3/system/android/AndroidConfigChooser.java +++ b/engine/src/android/com/jme3/system/android/AndroidConfigChooser.java @@ -2,9 +2,8 @@ package com.jme3.system.android; import android.graphics.PixelFormat; import android.opengl.GLSurfaceView.EGLConfigChooser; +import com.jme3.renderer.android.RendererUtil; import com.jme3.system.AppSettings; -import java.util.ArrayList; -import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.microedition.khronos.egl.EGL10; @@ -20,9 +19,6 @@ public class AndroidConfigChooser implements EGLConfigChooser { private static final Logger logger = Logger.getLogger(AndroidConfigChooser.class.getName()); public final static String SETTINGS_CONFIG_TYPE = "configType"; - protected int clientOpenGLESVersion = 0; - protected EGLConfig bestConfig = null; - protected EGLConfig fastestConfig = null; protected EGLConfig choosenConfig = null; protected AppSettings settings; protected int pixelFormat; @@ -91,14 +87,30 @@ public class AndroidConfigChooser implements EGLConfigChooser { this.settings = settings; } + private static int eglGetConfigAttribSafe(EGL10 egl, EGLDisplay display, EGLConfig config, int attribute) { + int[] value = new int[1]; + if (!egl.eglGetConfigAttrib(display, config, attribute, value)) { + RendererUtil.checkEGLError(egl); + throw new AssertionError(); + } + return value[0]; + } + /** * Gets called by the GLSurfaceView class to return the best config */ @Override public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { - logger.fine("GLSurfaceView asks for egl config, returning: "); - logEGLConfig(choosenConfig, display, egl, Level.FINE); - return choosenConfig; + logger.fine("GLSurfaceView asking for egl config"); + boolean configFound = findConfig(egl, display); + if (configFound) { + logger.fine("GLSurfaceView asks for egl config, returning: "); + logEGLConfig(choosenConfig, display, egl, Level.FINE); + return choosenConfig; + } else { + logger.fine("GLSurfaceView asks for egl config, No config found"); + return null; + } } /** @@ -108,7 +120,7 @@ public class AndroidConfigChooser implements EGLConfigChooser { * @param display * @return true if successfull, false if no config was found */ - public boolean findConfig(EGL10 egl, EGLDisplay display) { + private boolean findConfig(EGL10 egl, EGLDisplay display) { ConfigType type = (ConfigType) settings.get(SETTINGS_CONFIG_TYPE); ComponentSizeChooser compChooser = new ComponentSizeChooser(type, settings.getSamples()); @@ -116,48 +128,46 @@ public class AndroidConfigChooser implements EGLConfigChooser { logger.log(Level.FINE, "JME3 using {0} EGL configuration available here: ", type.name()); if (choosenConfig != null) { + // Remember the display for which we have the EGLConfig for logger.info("JME3 using choosen config: "); logEGLConfig(choosenConfig, display, egl, Level.INFO); pixelFormat = getPixelFormat(choosenConfig, display, egl); - clientOpenGLESVersion = getOpenGLVersion(choosenConfig, display, egl); return true; } else { logger.severe("ERROR: Unable to get a valid OpenGL ES 2.0 config, neither Fastest nor Best found! Bug. Please report this."); - clientOpenGLESVersion = 1; pixelFormat = PixelFormat.UNKNOWN; return false; } } private int getPixelFormat(EGLConfig conf, EGLDisplay display, EGL10 egl) { - int[] value = new int[1]; - //Android Pixel format is not very well documented. //From what i gathered, the format is chosen automatically except for the alpha channel //if the alpha channel has 8 bit or more, e set the pixel format to Transluscent, as it allow transparent view background //if it's 0 bit, the format is OPAQUE otherwise it's TRANSPARENT - egl.eglGetConfigAttrib(display, conf, EGL10.EGL_ALPHA_SIZE, value); - if (value[0] >= 8) { + int result = eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_ALPHA_SIZE); + + if (result >= 8) { + logger.log(Level.FINE, "Pixel Format: TRANSLUCENT"); return PixelFormat.TRANSLUCENT; } - if (value[0] >= 1) { + if (result >= 1) { + logger.log(Level.FINE, "Pixel Format: TRANSPARENT"); return PixelFormat.TRANSPARENT; } + logger.log(Level.FINE, "Pixel Format: OPAQUE"); return PixelFormat.OPAQUE; } private int getOpenGLVersion(EGLConfig conf, EGLDisplay display, EGL10 egl) { - int[] value = new int[1]; - int result = 1; - - egl.eglGetConfigAttrib(display, conf, EGL10.EGL_RENDERABLE_TYPE, value); + int val = eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_RENDERABLE_TYPE); // Check if conf is OpenGL ES 2.0 - if ((value[0] & EGL_OPENGL_ES2_BIT) != 0) { - result = 2; + if ((val & EGL_OPENGL_ES2_BIT) != 0) { + return 2; + } else { + return 1; } - - return result; } /** @@ -167,50 +177,37 @@ public class AndroidConfigChooser implements EGLConfigChooser { * @param display * @param egl */ - public void logEGLConfig(EGLConfig conf, EGLDisplay display, EGL10 egl, Level level) { - int[] value = new int[1]; - - egl.eglGetConfigAttrib(display, conf, EGL10.EGL_RED_SIZE, value); - logger.log(level, String.format("EGL_RED_SIZE = %d", value[0])); + private void logEGLConfig(EGLConfig conf, EGLDisplay display, EGL10 egl, Level level) { - egl.eglGetConfigAttrib(display, conf, EGL10.EGL_GREEN_SIZE, value); - logger.log(level, String.format("EGL_GREEN_SIZE = %d", value[0])); + logger.log(level, "EGL_RED_SIZE = {0}", + eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_RED_SIZE)); - egl.eglGetConfigAttrib(display, conf, EGL10.EGL_BLUE_SIZE, value); - logger.log(level, String.format("EGL_BLUE_SIZE = %d", value[0])); + logger.log(level, "EGL_GREEN_SIZE = {0}", + eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_GREEN_SIZE)); - egl.eglGetConfigAttrib(display, conf, EGL10.EGL_ALPHA_SIZE, value); - logger.log(level, String.format("EGL_ALPHA_SIZE = %d", value[0])); + logger.log(level, "EGL_BLUE_SIZE = {0}", + eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_BLUE_SIZE)); - egl.eglGetConfigAttrib(display, conf, EGL10.EGL_DEPTH_SIZE, value); - logger.log(level, String.format("EGL_DEPTH_SIZE = %d", value[0])); + logger.log(level, "EGL_ALPHA_SIZE = {0}", + eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_ALPHA_SIZE)); - egl.eglGetConfigAttrib(display, conf, EGL10.EGL_STENCIL_SIZE, value); - logger.log(level, String.format("EGL_STENCIL_SIZE = %d", value[0])); + logger.log(level, "EGL_DEPTH_SIZE = {0}", + eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_DEPTH_SIZE)); - egl.eglGetConfigAttrib(display, conf, EGL10.EGL_RENDERABLE_TYPE, value); - logger.log(level, String.format("EGL_RENDERABLE_TYPE = %d", value[0])); + logger.log(level, "EGL_STENCIL_SIZE = {0}", + eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_STENCIL_SIZE)); - egl.eglGetConfigAttrib(display, conf, EGL10.EGL_SURFACE_TYPE, value); - logger.log(level, String.format("EGL_SURFACE_TYPE = %d", value[0])); + logger.log(level, "EGL_RENDERABLE_TYPE = {0}", + eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_RENDERABLE_TYPE)); - egl.eglGetConfigAttrib(display, conf, EGL10.EGL_SAMPLE_BUFFERS, value); - logger.log(level, String.format("EGL_SAMPLE_BUFFERS = %d", value[0])); - - egl.eglGetConfigAttrib(display, conf, EGL10.EGL_SAMPLES, value); - logger.log(level, String.format("EGL_SAMPLES = %d", value[0])); - } + logger.log(level, "EGL_SURFACE_TYPE = {0}", + eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_SURFACE_TYPE)); - public int getClientOpenGLESVersion() { - return clientOpenGLESVersion; - } - - public void setClientOpenGLESVersion(int clientOpenGLESVersion) { - this.clientOpenGLESVersion = clientOpenGLESVersion; - } + logger.log(level, "EGL_SAMPLE_BUFFERS = {0}", + eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_SAMPLE_BUFFERS)); - public int getPixelFormat() { - return pixelFormat; + logger.log(level, "EGL_SAMPLES = {0}", + eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_SAMPLES)); } private abstract class BaseConfigChooser implements EGLConfigChooser { @@ -226,11 +223,17 @@ public class AndroidConfigChooser implements EGLConfigChooser { EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL10.EGL_NONE}; - egl.eglChooseConfig(display, configSpec, null, 0, num_config); + if (!egl.eglChooseConfig(display, configSpec, null, 0, num_config)) { + RendererUtil.checkEGLError(egl); + throw new AssertionError(); + } int numConfigs = num_config[0]; EGLConfig[] configs = new EGLConfig[numConfigs]; - egl.eglChooseConfig(display, configSpec, configs, numConfigs, num_config); + if (!egl.eglChooseConfig(display, configSpec, configs, numConfigs, num_config)) { + RendererUtil.checkEGLError(egl); + throw new AssertionError(); + } logger.fine("--------------Display Configurations---------------"); for (EGLConfig eGLConfig : configs) { @@ -252,12 +255,10 @@ public class AndroidConfigChooser implements EGLConfigChooser { */ private class ComponentSizeChooser extends BaseConfigChooser { - private int[] mValue; private ConfigType configType; protected int mSamples; public ComponentSizeChooser(ConfigType configType, int samples) { - mValue = new int[1]; mSamples = samples; this.configType = configType; } @@ -272,22 +273,22 @@ public class AndroidConfigChooser implements EGLConfigChooser { // first pass through config list. Try to find an exact match. for (EGLConfig config : configs) { - int r = findConfigAttrib(egl, display, config, - EGL10.EGL_RED_SIZE, 0); - int g = findConfigAttrib(egl, display, config, - EGL10.EGL_GREEN_SIZE, 0); - int b = findConfigAttrib(egl, display, config, - EGL10.EGL_BLUE_SIZE, 0); - int a = findConfigAttrib(egl, display, config, - EGL10.EGL_ALPHA_SIZE, 0); - int d = findConfigAttrib(egl, display, config, - EGL10.EGL_DEPTH_SIZE, 0); - int s = findConfigAttrib(egl, display, config, - EGL10.EGL_STENCIL_SIZE, 0); - int isMs = findConfigAttrib(egl, display, config, - EGL10.EGL_SAMPLE_BUFFERS, 0); - int nbMs = findConfigAttrib(egl, display, config, - EGL10.EGL_SAMPLES, 0); + int r = eglGetConfigAttribSafe(egl, display, config, + EGL10.EGL_RED_SIZE); + int g = eglGetConfigAttribSafe(egl, display, config, + EGL10.EGL_GREEN_SIZE); + int b = eglGetConfigAttribSafe(egl, display, config, + EGL10.EGL_BLUE_SIZE); + int a = eglGetConfigAttribSafe(egl, display, config, + EGL10.EGL_ALPHA_SIZE); + int d = eglGetConfigAttribSafe(egl, display, config, + EGL10.EGL_DEPTH_SIZE); + int s = eglGetConfigAttribSafe(egl, display, config, + EGL10.EGL_STENCIL_SIZE); + int isMs = eglGetConfigAttribSafe(egl, display, config, + EGL10.EGL_SAMPLE_BUFFERS); + int nbMs = eglGetConfigAttribSafe(egl, display, config, + EGL10.EGL_SAMPLES); if (inRange(r, configType.mr, configType.r) && inRange(g, configType.mg, configType.g) @@ -344,13 +345,13 @@ public class AndroidConfigChooser implements EGLConfigChooser { return keptConfig; } } - + logger.log(Level.WARNING, "Failed to find a suitable display configuration for FASTEST, hoping for the best..."); // failsafe. pick the 1st config with a 16 bit depth buffer. for (EGLConfig config : configs) { - int d = findConfigAttrib(egl, display, config, - EGL10.EGL_DEPTH_SIZE, 0); + int d = eglGetConfigAttribSafe(egl, display, config, + EGL10.EGL_DEPTH_SIZE); if (d >= 16) { return config; } @@ -363,15 +364,6 @@ public class AndroidConfigChooser implements EGLConfigChooser { private boolean inRange(int val, int min, int max) { return min <= val && val <= max; } - - private int findConfigAttrib(EGL10 egl, EGLDisplay display, - EGLConfig config, int attribute, int defaultValue) { - - if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) { - return mValue[0]; - } - return defaultValue; - } } //DON'T REMOVE THIS, USED FOR UNIT TESTING FAILING CONFIGURATION LISTS. // private static class Config { diff --git a/engine/src/android/com/jme3/system/android/OGLESContext.java b/engine/src/android/com/jme3/system/android/OGLESContext.java index c51c4eca8..d6bd64ddf 100644 --- a/engine/src/android/com/jme3/system/android/OGLESContext.java +++ b/engine/src/android/com/jme3/system/android/OGLESContext.java @@ -32,11 +32,15 @@ package com.jme3.system.android; import android.app.Activity; -import com.jme3.renderer.android.AndroidGLSurfaceView; +import android.app.ActivityManager; import android.app.AlertDialog; +import android.content.Context; import android.content.DialogInterface; +import android.content.pm.ConfigurationInfo; +import android.graphics.PixelFormat; import android.opengl.GLSurfaceView; import android.text.InputType; +import android.util.Log; import android.view.Gravity; import android.view.SurfaceHolder; import android.view.ViewGroup.LayoutParams; @@ -48,16 +52,16 @@ import com.jme3.input.android.AndroidSensorJoyInput; import com.jme3.input.controls.SoftTextDialogInputListener; import com.jme3.input.dummy.DummyKeyInput; import com.jme3.input.dummy.DummyMouseInput; +import com.jme3.renderer.android.AndroidGLSurfaceView; +import com.jme3.renderer.RendererException; import com.jme3.renderer.android.OGLESShaderRenderer; +import com.jme3.renderer.android.RendererUtil; import com.jme3.system.*; import com.jme3.system.android.AndroidConfigChooser.ConfigType; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; 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; public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTextDialogInput { @@ -91,7 +95,7 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex public Type getType() { return Type.Display; } - + /** * createView creates the GLSurfaceView that the renderer will * draw to.

The result GLSurfaceView will receive input events and @@ -104,27 +108,27 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex * ConfigType.BEST * @param eglConfigVerboseLogging if true show all found configs * @return GLSurfaceView The newly created view - * @deprecated AndroidGLSurfaceView createView() + * @deprecated AndroidGLSurfaceView createView() * and put the configType in the appSettigs with the key AndroidConfigChoose.SETTINGS_CONFIG_TYPE */ @Deprecated public AndroidGLSurfaceView createView(ConfigType configType, boolean eglConfigVerboseLogging) { settings.put(AndroidConfigChooser.SETTINGS_CONFIG_TYPE, configType); - return this.createView(); + return this.createView(); } /** * createView creates the GLSurfaceView that the renderer will * draw to.

The result GLSurfaceView will receive input events and * forward them to the Application. Any rendering will be done into the * GLSurfaceView. Only one GLSurfaceView can be created at this time. The - * given configType specifies how to determine the display configuration. + * given configType specifies how to determine the display configuration. + * * - * * @param eglConfigVerboseLogging if true show all found configs * @return GLSurfaceView The newly created view */ public AndroidGLSurfaceView createView() { - AndroidGLSurfaceView view; + AndroidGLSurfaceView view; ConfigType configType = (ConfigType)settings.get(AndroidConfigChooser.SETTINGS_CONFIG_TYPE); // Start to set up the view @@ -135,60 +139,60 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex androidInput.setView(view); androidInput.loadSettings(settings); - if (configType == ConfigType.LEGACY) { - // Hardcoded egl setup - clientOpenGLESVersion = 2; - view.setEGLContextClientVersion(2); - // RGB565, Depth16 - view.setEGLConfigChooser(5, 6, 5, 0, 16, 0); - logger.fine("ConfigType.LEGACY using RGB565"); + int rawOpenGLESVersion = getOpenGLESVersion(); + logger.log(Level.FINE, "clientOpenGLESVersion {0}.{1}", + new Object[]{clientOpenGLESVersion>>16, clientOpenGLESVersion<<16}); + if (rawOpenGLESVersion < 0x20000) { + throw new UnsupportedOperationException("OpenGL ES 2.0 is not supported on this device"); } else { - 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.log(Level.INFO, "Display EGL Version: {0}.{1}", new Object[]{version[0], version[1]}); - } - - try { - // Create a config chooser - AndroidConfigChooser configChooser = new AndroidConfigChooser(settings); - // Init chooser - if (!configChooser.findConfig(egl, display)) { - listener.handleError("Unable to find suitable EGL config", null); - return null; - } - - clientOpenGLESVersion = configChooser.getClientOpenGLESVersion(); - if (clientOpenGLESVersion < 2) { - listener.handleError("OpenGL ES 2.0 is not supported on this device", null); - return null; - } - - // Requesting client version from GLSurfaceView which is extended by - // AndroidInput. - view.setEGLContextClientVersion(clientOpenGLESVersion); - view.setEGLConfigChooser(configChooser); - view.getHolder().setFormat(configChooser.getPixelFormat()); - } finally { - if (display != null) { - egl.eglTerminate(display); - } - } + clientOpenGLESVersion = 2; + view.setEGLContextClientVersion(clientOpenGLESVersion); } view.setFocusableInTouchMode(true); view.setFocusable(true); view.getHolder().setType(SurfaceHolder.SURFACE_TYPE_GPU); - if (configType == ConfigType.BEST_TRANSLUCENT) { - //This is important to allow the GL surface to have a translucent background + + // setFormat must be set before AndroidConfigChooser is called by the surfaceview. + // if setFormat is called after ConfigChooser is called, then execution + // stops at the setFormat call without a crash. + // We look at the user setting for alpha bits and set the surfaceview + // PixelFormat to either Opaque, Transparent, or Translucent. + // ConfigChooser will do it's best to honor the alpha requested by the user + // For best rendering performance, use Opaque (alpha bits = 0). + int alphaBits = configType.a; + logger.log(Level.FINE, "alphaBits: {0}", alphaBits); + if (alphaBits >= 8) { + logger.log(Level.FINE, "Pixel Format: TRANSLUCENT"); + view.getHolder().setFormat(PixelFormat.TRANSLUCENT); view.setZOrderOnTop(true); + } else if (alphaBits >= 1) { + logger.log(Level.FINE, "Pixel Format: TRANSPARENT"); + view.getHolder().setFormat(PixelFormat.TRANSPARENT); + } else { + logger.log(Level.FINE, "Pixel Format: OPAQUE"); + view.getHolder().setFormat(PixelFormat.OPAQUE); } + + AndroidConfigChooser configChooser = new AndroidConfigChooser(settings); + view.setEGLConfigChooser(configChooser); + view.setRenderer(this); return view; } + /** + * Get the OpenGL ES version + * @return version returns the int value of the GLES version + */ + public int getOpenGLESVersion() { + ActivityManager am = + (ActivityManager) JmeAndroidSystem.getActivity().getApplication().getSystemService(Context.ACTIVITY_SERVICE); + ConfigurationInfo info = am.getDeviceConfigurationInfo(); + logger.log(Level.FINE, "OpenGL Version {0}:", info.getGlEsVersion()); + return info.reqGlEsVersion; +// return (info.reqGlEsVersion >= 0x20000); + } // renderer:initialize @Override @@ -218,10 +222,6 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex } }); - if (clientOpenGLESVersion < 2) { - throw new UnsupportedOperationException("OpenGL ES 2.0 is not supported on this device"); - } - timer = new AndroidTimer(); renderer = new OGLESShaderRenderer(); @@ -405,10 +405,6 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex } } - public int getClientOpenGLESVersion() { - return clientOpenGLESVersion; - } - public void requestDialog(final int id, final String title, final String initialValue, final SoftTextDialogInputListener listener) { logger.log(Level.FINE, "requestDialog: title: {0}, initialValue: {1}", new Object[]{title, initialValue});