Android: Modify EGLConfigChooser to evaluate available configs when asked by the surface. More to come to clean up this area. Addresses issue: http://hub.jmonkeyengine.org/forum/topic/crash-nexus-10-android-4-3/

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10798 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
experimental
iwg..ic 12 years ago
parent 5a1e7dbd63
commit 2711e729d0
  1. 52
      engine/src/android/com/jme3/system/android/AndroidConfigChooser.java
  2. 101
      engine/src/android/com/jme3/system/android/OGLESContext.java

@ -1,8 +1,8 @@
package com.jme3.system.android; package com.jme3.system.android;
import android.graphics.PixelFormat; import android.graphics.PixelFormat;
import android.opengl.GLSurfaceView;
import android.opengl.GLSurfaceView.EGLConfigChooser; import android.opengl.GLSurfaceView.EGLConfigChooser;
import com.jme3.renderer.RendererException;
import com.jme3.renderer.android.RendererUtil; import com.jme3.renderer.android.RendererUtil;
import com.jme3.system.AppSettings; import com.jme3.system.AppSettings;
import java.util.logging.Level; import java.util.logging.Level;
@ -20,12 +20,10 @@ public class AndroidConfigChooser implements EGLConfigChooser {
private static final Logger logger = Logger.getLogger(AndroidConfigChooser.class.getName()); private static final Logger logger = Logger.getLogger(AndroidConfigChooser.class.getName());
public final static String SETTINGS_CONFIG_TYPE = "configType"; 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 EGLConfig choosenConfig = null;
protected EGLDisplay configForDisplay = null; protected EGLDisplay configForDisplay = null;
protected AppSettings settings; protected AppSettings settings;
protected GLSurfaceView view;
protected int pixelFormat; protected int pixelFormat;
protected boolean verbose = false; protected boolean verbose = false;
private final static int EGL_OPENGL_ES2_BIT = 4; private final static int EGL_OPENGL_ES2_BIT = 4;
@ -92,6 +90,11 @@ public class AndroidConfigChooser implements EGLConfigChooser {
this.settings = settings; this.settings = settings;
} }
public AndroidConfigChooser(AppSettings settings, GLSurfaceView view) {
this(settings);
this.view = view;
}
private static int eglGetConfigAttribSafe(EGL10 egl, EGLDisplay display, EGLConfig config, int attribute) { private static int eglGetConfigAttribSafe(EGL10 egl, EGLDisplay display, EGLConfig config, int attribute) {
int[] value = new int[1]; int[] value = new int[1];
if (!egl.eglGetConfigAttrib(display, config, attribute, value)) { if (!egl.eglGetConfigAttrib(display, config, attribute, value)) {
@ -100,18 +103,23 @@ public class AndroidConfigChooser implements EGLConfigChooser {
} }
return value[0]; return value[0];
} }
/** /**
* Gets called by the GLSurfaceView class to return the best config * Gets called by the GLSurfaceView class to return the best config
*/ */
@Override @Override
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
if (configForDisplay != display) { logger.fine("GLSurfaceView asking for egl config");
throw new RendererException("The display used for finding config is not the same as the render display"); boolean configFound = findConfig(egl, display);
if (configFound) {
logger.fine("GLSurfaceView asks for egl config, returning: ");
logEGLConfig(choosenConfig, display, egl, Level.FINE);
view.getHolder().setFormat(pixelFormat);
return choosenConfig;
} else {
logger.fine("GLSurfaceView asks for egl config, No config found");
return null;
} }
logger.fine("GLSurfaceView asks for egl config, returning: ");
logEGLConfig(choosenConfig, display, egl, Level.FINE);
return choosenConfig;
} }
/** /**
@ -121,7 +129,7 @@ public class AndroidConfigChooser implements EGLConfigChooser {
* @param display * @param display
* @return true if successfull, false if no config was found * @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); ConfigType type = (ConfigType) settings.get(SETTINGS_CONFIG_TYPE);
ComponentSizeChooser compChooser = new ComponentSizeChooser(type, settings.getSamples()); ComponentSizeChooser compChooser = new ComponentSizeChooser(type, settings.getSamples());
@ -134,11 +142,12 @@ public class AndroidConfigChooser implements EGLConfigChooser {
logger.info("JME3 using choosen config: "); logger.info("JME3 using choosen config: ");
logEGLConfig(choosenConfig, display, egl, Level.INFO); logEGLConfig(choosenConfig, display, egl, Level.INFO);
pixelFormat = getPixelFormat(choosenConfig, display, egl); pixelFormat = getPixelFormat(choosenConfig, display, egl);
clientOpenGLESVersion = getOpenGLVersion(choosenConfig, display, egl); if (pixelFormat == PixelFormat.TRANSLUCENT) {
view.setZOrderOnTop(true);
}
return true; return true;
} else { } else {
logger.severe("ERROR: Unable to get a valid OpenGL ES 2.0 config, neither Fastest nor Best found! Bug. Please report this."); 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; pixelFormat = PixelFormat.UNKNOWN;
return false; return false;
} }
@ -152,12 +161,15 @@ public class AndroidConfigChooser implements EGLConfigChooser {
int result = eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_ALPHA_SIZE); int result = eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_ALPHA_SIZE);
if (result >= 8) { if (result >= 8) {
logger.log(Level.FINE, "Pixel Format: TRANSLUCENT");
return PixelFormat.TRANSLUCENT; return PixelFormat.TRANSLUCENT;
} }
if (result >= 1) { if (result >= 1) {
logger.log(Level.FINE, "Pixel Format: TRANSPARENT");
return PixelFormat.TRANSPARENT; return PixelFormat.TRANSPARENT;
} }
logger.log(Level.FINE, "Pixel Format: OPAQUE");
return PixelFormat.OPAQUE; return PixelFormat.OPAQUE;
} }
@ -178,7 +190,7 @@ public class AndroidConfigChooser implements EGLConfigChooser {
* @param display * @param display
* @param egl * @param egl
*/ */
public void logEGLConfig(EGLConfig conf, EGLDisplay display, EGL10 egl, Level level) { private void logEGLConfig(EGLConfig conf, EGLDisplay display, EGL10 egl, Level level) {
logger.log(level, "EGL_RED_SIZE = {0}", logger.log(level, "EGL_RED_SIZE = {0}",
eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_RED_SIZE)); eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_RED_SIZE));
@ -211,18 +223,6 @@ public class AndroidConfigChooser implements EGLConfigChooser {
eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_SAMPLES)); eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_SAMPLES));
} }
public int getClientOpenGLESVersion() {
return clientOpenGLESVersion;
}
public void setClientOpenGLESVersion(int clientOpenGLESVersion) {
this.clientOpenGLESVersion = clientOpenGLESVersion;
}
public int getPixelFormat() {
return pixelFormat;
}
private abstract class BaseConfigChooser implements EGLConfigChooser { private abstract class BaseConfigChooser implements EGLConfigChooser {
public BaseConfigChooser() { public BaseConfigChooser() {

@ -32,11 +32,14 @@
package com.jme3.system.android; package com.jme3.system.android;
import android.app.Activity; import android.app.Activity;
import com.jme3.renderer.android.AndroidGLSurfaceView; import android.app.ActivityManager;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.pm.ConfigurationInfo;
import android.opengl.GLSurfaceView; import android.opengl.GLSurfaceView;
import android.text.InputType; import android.text.InputType;
import android.util.Log;
import android.view.Gravity; import android.view.Gravity;
import android.view.SurfaceHolder; import android.view.SurfaceHolder;
import android.view.ViewGroup.LayoutParams; import android.view.ViewGroup.LayoutParams;
@ -48,6 +51,7 @@ import com.jme3.input.android.AndroidSensorJoyInput;
import com.jme3.input.controls.SoftTextDialogInputListener; import com.jme3.input.controls.SoftTextDialogInputListener;
import com.jme3.input.dummy.DummyKeyInput; import com.jme3.input.dummy.DummyKeyInput;
import com.jme3.input.dummy.DummyMouseInput; import com.jme3.input.dummy.DummyMouseInput;
import com.jme3.renderer.android.AndroidGLSurfaceView;
import com.jme3.renderer.RendererException; import com.jme3.renderer.RendererException;
import com.jme3.renderer.android.OGLESShaderRenderer; import com.jme3.renderer.android.OGLESShaderRenderer;
import com.jme3.renderer.android.RendererUtil; import com.jme3.renderer.android.RendererUtil;
@ -56,10 +60,7 @@ import com.jme3.system.android.AndroidConfigChooser.ConfigType;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.opengles.GL10;
public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTextDialogInput { public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTextDialogInput {
@ -93,7 +94,7 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
public Type getType() { public Type getType() {
return Type.Display; return Type.Display;
} }
/** /**
* <code>createView</code> creates the GLSurfaceView that the renderer will * <code>createView</code> creates the GLSurfaceView that the renderer will
* draw to. <p> The result GLSurfaceView will receive input events and * draw to. <p> The result GLSurfaceView will receive input events and
@ -106,27 +107,27 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
* ConfigType.BEST * ConfigType.BEST
* @param eglConfigVerboseLogging if true show all found configs * @param eglConfigVerboseLogging if true show all found configs
* @return GLSurfaceView The newly created view * @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 * and put the configType in the appSettigs with the key AndroidConfigChoose.SETTINGS_CONFIG_TYPE
*/ */
@Deprecated @Deprecated
public AndroidGLSurfaceView createView(ConfigType configType, boolean eglConfigVerboseLogging) { public AndroidGLSurfaceView createView(ConfigType configType, boolean eglConfigVerboseLogging) {
settings.put(AndroidConfigChooser.SETTINGS_CONFIG_TYPE, configType); settings.put(AndroidConfigChooser.SETTINGS_CONFIG_TYPE, configType);
return this.createView(); return this.createView();
} }
/** /**
* <code>createView</code> creates the GLSurfaceView that the renderer will * <code>createView</code> creates the GLSurfaceView that the renderer will
* draw to. <p> The result GLSurfaceView will receive input events and * draw to. <p> The result GLSurfaceView will receive input events and
* forward them to the Application. Any rendering will be done into the * forward them to the Application. Any rendering will be done into the
* GLSurfaceView. Only one GLSurfaceView can be created at this time. 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 * @param eglConfigVerboseLogging if true show all found configs
* @return GLSurfaceView The newly created view * @return GLSurfaceView The newly created view
*/ */
public AndroidGLSurfaceView createView() { public AndroidGLSurfaceView createView() {
AndroidGLSurfaceView view; AndroidGLSurfaceView view;
ConfigType configType = (ConfigType)settings.get(AndroidConfigChooser.SETTINGS_CONFIG_TYPE); ConfigType configType = (ConfigType)settings.get(AndroidConfigChooser.SETTINGS_CONFIG_TYPE);
// Start to set up the view // Start to set up the view
@ -137,65 +138,39 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
androidInput.setView(view); androidInput.setView(view);
androidInput.loadSettings(settings); androidInput.loadSettings(settings);
if (configType == ConfigType.LEGACY) { int rawOpenGLESVersion = getOpenGLESVersion();
// Hardcoded egl setup logger.log(Level.FINE, "clientOpenGLESVersion {0}.{1}",
clientOpenGLESVersion = 2; new Object[]{clientOpenGLESVersion>>16, clientOpenGLESVersion<<16});
view.setEGLContextClientVersion(2); if (rawOpenGLESVersion < 0x20000) {
// RGB565, Depth16 throw new UnsupportedOperationException("OpenGL ES 2.0 is not supported on this device");
view.setEGLConfigChooser(5, 6, 5, 0, 16, 0);
logger.fine("ConfigType.LEGACY using RGB565");
} else { } else {
EGL10 egl = (EGL10) EGLContext.getEGL(); clientOpenGLESVersion = 2;
EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); view.setEGLContextClientVersion(clientOpenGLESVersion);
if (display == EGL10.EGL_NO_DISPLAY) {
throw new RendererException("No default EGL display is available");
}
int[] version = new int[2];
if (!egl.eglInitialize(display, version)) {
RendererUtil.checkEGLError(egl);
}
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 && display != EGL10.EGL_NO_DISPLAY) {
egl.eglTerminate(display);
}
}
} }
view.setFocusableInTouchMode(true); view.setFocusableInTouchMode(true);
view.setFocusable(true); view.setFocusable(true);
view.getHolder().setType(SurfaceHolder.SURFACE_TYPE_GPU); 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 AndroidConfigChooser configChooser = new AndroidConfigChooser(settings, view);
view.setZOrderOnTop(true); view.setEGLConfigChooser(configChooser);
}
view.setRenderer(this); view.setRenderer(this);
return view; 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 // renderer:initialize
@Override @Override
@ -225,10 +200,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(); timer = new AndroidTimer();
renderer = new OGLESShaderRenderer(); renderer = new OGLESShaderRenderer();
@ -412,10 +383,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) { public void requestDialog(final int id, final String title, final String initialValue, final SoftTextDialogInputListener listener) {
logger.log(Level.FINE, "requestDialog: title: {0}, initialValue: {1}", logger.log(Level.FINE, "requestDialog: title: {0}, initialValue: {1}",
new Object[]{title, initialValue}); new Object[]{title, initialValue});

Loading…
Cancel
Save