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
This commit is contained in:
parent
f4b4fc9c1e
commit
33db5460c3
@ -3,23 +3,27 @@ package com.jme3.renderer.android;
|
|||||||
import android.opengl.GLES20;
|
import android.opengl.GLES20;
|
||||||
import android.opengl.GLU;
|
import android.opengl.GLU;
|
||||||
import com.jme3.renderer.RendererException;
|
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
|
* @author Kirill Vainer
|
||||||
*/
|
*/
|
||||||
public class RendererUtil {
|
public class RendererUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When set to true, every OpenGL call will check for errors and throw
|
* When set to true, every OpenGL call will check for errors and throw an
|
||||||
* an exception if there is one, if false, no error checking is performed.
|
* exception if there is one, if false, no error checking is performed.
|
||||||
*/
|
*/
|
||||||
public static boolean ENABLE_ERROR_CHECKING = true;
|
public static boolean ENABLE_ERROR_CHECKING = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks for an OpenGL error and throws a {@link RendererException}
|
* Checks for an OpenGL error and throws a {@link RendererException} if
|
||||||
* if there is one. Ignores the value of {@link RendererUtil#ENABLE_ERROR_CHECKING}.
|
* there is one. Ignores the value of
|
||||||
|
* {@link RendererUtil#ENABLE_ERROR_CHECKING}.
|
||||||
*/
|
*/
|
||||||
public static void checkGLErrorForced() {
|
public static void checkGLErrorForced() {
|
||||||
int error = GLES20.glGetError();
|
int error = GLES20.glGetError();
|
||||||
@ -34,12 +38,84 @@ public class RendererUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks for an OpenGL error and throws a {@link RendererException}
|
* Checks for an EGL error and throws a {@link RendererException} if there
|
||||||
* if there is one. Does nothing if {@link RendererUtil#ENABLE_ERROR_CHECKING}
|
* is one. Ignores the value of {@link RendererUtil#ENABLE_ERROR_CHECKING}.
|
||||||
* is set to <code>false</code>.
|
*/
|
||||||
|
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
|
||||||
|
* <code>false</code>.
|
||||||
*/
|
*/
|
||||||
public static void checkGLError() {
|
public static void checkGLError() {
|
||||||
if (!ENABLE_ERROR_CHECKING) return;
|
if (!ENABLE_ERROR_CHECKING) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
int error = GLES20.glGetError();
|
int error = GLES20.glGetError();
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
String message = GLU.gluErrorString(error);
|
String message = GLU.gluErrorString(error);
|
||||||
|
@ -2,9 +2,8 @@ package com.jme3.system.android;
|
|||||||
|
|
||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
import android.opengl.GLSurfaceView.EGLConfigChooser;
|
import android.opengl.GLSurfaceView.EGLConfigChooser;
|
||||||
|
import com.jme3.renderer.android.RendererUtil;
|
||||||
import com.jme3.system.AppSettings;
|
import com.jme3.system.AppSettings;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
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.EGL10;
|
||||||
@ -20,9 +19,6 @@ 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 AppSettings settings;
|
protected AppSettings settings;
|
||||||
protected int pixelFormat;
|
protected int pixelFormat;
|
||||||
@ -91,14 +87,30 @@ public class AndroidConfigChooser implements EGLConfigChooser {
|
|||||||
this.settings = settings;
|
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
|
* 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) {
|
||||||
|
logger.fine("GLSurfaceView asking for egl config");
|
||||||
|
boolean configFound = findConfig(egl, display);
|
||||||
|
if (configFound) {
|
||||||
logger.fine("GLSurfaceView asks for egl config, returning: ");
|
logger.fine("GLSurfaceView asks for egl config, returning: ");
|
||||||
logEGLConfig(choosenConfig, display, egl, Level.FINE);
|
logEGLConfig(choosenConfig, display, egl, Level.FINE);
|
||||||
return choosenConfig;
|
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
|
* @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());
|
||||||
@ -116,48 +128,46 @@ public class AndroidConfigChooser implements EGLConfigChooser {
|
|||||||
logger.log(Level.FINE, "JME3 using {0} EGL configuration available here: ", type.name());
|
logger.log(Level.FINE, "JME3 using {0} EGL configuration available here: ", type.name());
|
||||||
|
|
||||||
if (choosenConfig != null) {
|
if (choosenConfig != null) {
|
||||||
|
// Remember the display for which we have the EGLConfig for
|
||||||
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);
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getPixelFormat(EGLConfig conf, EGLDisplay display, EGL10 egl) {
|
private int getPixelFormat(EGLConfig conf, EGLDisplay display, EGL10 egl) {
|
||||||
int[] value = new int[1];
|
|
||||||
|
|
||||||
//Android Pixel format is not very well documented.
|
//Android Pixel format is not very well documented.
|
||||||
//From what i gathered, the format is chosen automatically except for the alpha channel
|
//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 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
|
//if it's 0 bit, the format is OPAQUE otherwise it's TRANSPARENT
|
||||||
egl.eglGetConfigAttrib(display, conf, EGL10.EGL_ALPHA_SIZE, value);
|
int result = eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_ALPHA_SIZE);
|
||||||
if (value[0] >= 8) {
|
|
||||||
|
if (result >= 8) {
|
||||||
|
logger.log(Level.FINE, "Pixel Format: TRANSLUCENT");
|
||||||
return PixelFormat.TRANSLUCENT;
|
return PixelFormat.TRANSLUCENT;
|
||||||
}
|
}
|
||||||
if (value[0] >= 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getOpenGLVersion(EGLConfig conf, EGLDisplay display, EGL10 egl) {
|
private int getOpenGLVersion(EGLConfig conf, EGLDisplay display, EGL10 egl) {
|
||||||
int[] value = new int[1];
|
int val = eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_RENDERABLE_TYPE);
|
||||||
int result = 1;
|
|
||||||
|
|
||||||
egl.eglGetConfigAttrib(display, conf, EGL10.EGL_RENDERABLE_TYPE, value);
|
|
||||||
// Check if conf is OpenGL ES 2.0
|
// Check if conf is OpenGL ES 2.0
|
||||||
if ((value[0] & EGL_OPENGL_ES2_BIT) != 0) {
|
if ((val & EGL_OPENGL_ES2_BIT) != 0) {
|
||||||
result = 2;
|
return 2;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -167,50 +177,37 @@ 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) {
|
||||||
int[] value = new int[1];
|
|
||||||
|
|
||||||
egl.eglGetConfigAttrib(display, conf, EGL10.EGL_RED_SIZE, value);
|
logger.log(level, "EGL_RED_SIZE = {0}",
|
||||||
logger.log(level, String.format("EGL_RED_SIZE = %d", value[0]));
|
eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_RED_SIZE));
|
||||||
|
|
||||||
egl.eglGetConfigAttrib(display, conf, EGL10.EGL_GREEN_SIZE, value);
|
logger.log(level, "EGL_GREEN_SIZE = {0}",
|
||||||
logger.log(level, String.format("EGL_GREEN_SIZE = %d", value[0]));
|
eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_GREEN_SIZE));
|
||||||
|
|
||||||
egl.eglGetConfigAttrib(display, conf, EGL10.EGL_BLUE_SIZE, value);
|
logger.log(level, "EGL_BLUE_SIZE = {0}",
|
||||||
logger.log(level, String.format("EGL_BLUE_SIZE = %d", value[0]));
|
eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_BLUE_SIZE));
|
||||||
|
|
||||||
egl.eglGetConfigAttrib(display, conf, EGL10.EGL_ALPHA_SIZE, value);
|
logger.log(level, "EGL_ALPHA_SIZE = {0}",
|
||||||
logger.log(level, String.format("EGL_ALPHA_SIZE = %d", value[0]));
|
eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_ALPHA_SIZE));
|
||||||
|
|
||||||
egl.eglGetConfigAttrib(display, conf, EGL10.EGL_DEPTH_SIZE, value);
|
logger.log(level, "EGL_DEPTH_SIZE = {0}",
|
||||||
logger.log(level, String.format("EGL_DEPTH_SIZE = %d", value[0]));
|
eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_DEPTH_SIZE));
|
||||||
|
|
||||||
egl.eglGetConfigAttrib(display, conf, EGL10.EGL_STENCIL_SIZE, value);
|
logger.log(level, "EGL_STENCIL_SIZE = {0}",
|
||||||
logger.log(level, String.format("EGL_STENCIL_SIZE = %d", value[0]));
|
eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_STENCIL_SIZE));
|
||||||
|
|
||||||
egl.eglGetConfigAttrib(display, conf, EGL10.EGL_RENDERABLE_TYPE, value);
|
logger.log(level, "EGL_RENDERABLE_TYPE = {0}",
|
||||||
logger.log(level, String.format("EGL_RENDERABLE_TYPE = %d", value[0]));
|
eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_RENDERABLE_TYPE));
|
||||||
|
|
||||||
egl.eglGetConfigAttrib(display, conf, EGL10.EGL_SURFACE_TYPE, value);
|
logger.log(level, "EGL_SURFACE_TYPE = {0}",
|
||||||
logger.log(level, String.format("EGL_SURFACE_TYPE = %d", value[0]));
|
eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_SURFACE_TYPE));
|
||||||
|
|
||||||
egl.eglGetConfigAttrib(display, conf, EGL10.EGL_SAMPLE_BUFFERS, value);
|
logger.log(level, "EGL_SAMPLE_BUFFERS = {0}",
|
||||||
logger.log(level, String.format("EGL_SAMPLE_BUFFERS = %d", value[0]));
|
eglGetConfigAttribSafe(egl, display, conf, EGL10.EGL_SAMPLE_BUFFERS));
|
||||||
|
|
||||||
egl.eglGetConfigAttrib(display, conf, EGL10.EGL_SAMPLES, value);
|
logger.log(level, "EGL_SAMPLES = {0}",
|
||||||
logger.log(level, String.format("EGL_SAMPLES = %d", value[0]));
|
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 {
|
||||||
@ -226,11 +223,17 @@ public class AndroidConfigChooser implements EGLConfigChooser {
|
|||||||
EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||||
EGL10.EGL_NONE};
|
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];
|
int numConfigs = num_config[0];
|
||||||
EGLConfig[] configs = new EGLConfig[numConfigs];
|
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---------------");
|
logger.fine("--------------Display Configurations---------------");
|
||||||
for (EGLConfig eGLConfig : configs) {
|
for (EGLConfig eGLConfig : configs) {
|
||||||
@ -252,12 +255,10 @@ public class AndroidConfigChooser implements EGLConfigChooser {
|
|||||||
*/
|
*/
|
||||||
private class ComponentSizeChooser extends BaseConfigChooser {
|
private class ComponentSizeChooser extends BaseConfigChooser {
|
||||||
|
|
||||||
private int[] mValue;
|
|
||||||
private ConfigType configType;
|
private ConfigType configType;
|
||||||
protected int mSamples;
|
protected int mSamples;
|
||||||
|
|
||||||
public ComponentSizeChooser(ConfigType configType, int samples) {
|
public ComponentSizeChooser(ConfigType configType, int samples) {
|
||||||
mValue = new int[1];
|
|
||||||
mSamples = samples;
|
mSamples = samples;
|
||||||
this.configType = configType;
|
this.configType = configType;
|
||||||
}
|
}
|
||||||
@ -272,22 +273,22 @@ public class AndroidConfigChooser implements EGLConfigChooser {
|
|||||||
|
|
||||||
// first pass through config list. Try to find an exact match.
|
// first pass through config list. Try to find an exact match.
|
||||||
for (EGLConfig config : configs) {
|
for (EGLConfig config : configs) {
|
||||||
int r = findConfigAttrib(egl, display, config,
|
int r = eglGetConfigAttribSafe(egl, display, config,
|
||||||
EGL10.EGL_RED_SIZE, 0);
|
EGL10.EGL_RED_SIZE);
|
||||||
int g = findConfigAttrib(egl, display, config,
|
int g = eglGetConfigAttribSafe(egl, display, config,
|
||||||
EGL10.EGL_GREEN_SIZE, 0);
|
EGL10.EGL_GREEN_SIZE);
|
||||||
int b = findConfigAttrib(egl, display, config,
|
int b = eglGetConfigAttribSafe(egl, display, config,
|
||||||
EGL10.EGL_BLUE_SIZE, 0);
|
EGL10.EGL_BLUE_SIZE);
|
||||||
int a = findConfigAttrib(egl, display, config,
|
int a = eglGetConfigAttribSafe(egl, display, config,
|
||||||
EGL10.EGL_ALPHA_SIZE, 0);
|
EGL10.EGL_ALPHA_SIZE);
|
||||||
int d = findConfigAttrib(egl, display, config,
|
int d = eglGetConfigAttribSafe(egl, display, config,
|
||||||
EGL10.EGL_DEPTH_SIZE, 0);
|
EGL10.EGL_DEPTH_SIZE);
|
||||||
int s = findConfigAttrib(egl, display, config,
|
int s = eglGetConfigAttribSafe(egl, display, config,
|
||||||
EGL10.EGL_STENCIL_SIZE, 0);
|
EGL10.EGL_STENCIL_SIZE);
|
||||||
int isMs = findConfigAttrib(egl, display, config,
|
int isMs = eglGetConfigAttribSafe(egl, display, config,
|
||||||
EGL10.EGL_SAMPLE_BUFFERS, 0);
|
EGL10.EGL_SAMPLE_BUFFERS);
|
||||||
int nbMs = findConfigAttrib(egl, display, config,
|
int nbMs = eglGetConfigAttribSafe(egl, display, config,
|
||||||
EGL10.EGL_SAMPLES, 0);
|
EGL10.EGL_SAMPLES);
|
||||||
|
|
||||||
if (inRange(r, configType.mr, configType.r)
|
if (inRange(r, configType.mr, configType.r)
|
||||||
&& inRange(g, configType.mg, configType.g)
|
&& inRange(g, configType.mg, configType.g)
|
||||||
@ -349,8 +350,8 @@ public class AndroidConfigChooser implements EGLConfigChooser {
|
|||||||
|
|
||||||
// failsafe. pick the 1st config with a 16 bit depth buffer.
|
// failsafe. pick the 1st config with a 16 bit depth buffer.
|
||||||
for (EGLConfig config : configs) {
|
for (EGLConfig config : configs) {
|
||||||
int d = findConfigAttrib(egl, display, config,
|
int d = eglGetConfigAttribSafe(egl, display, config,
|
||||||
EGL10.EGL_DEPTH_SIZE, 0);
|
EGL10.EGL_DEPTH_SIZE);
|
||||||
if (d >= 16) {
|
if (d >= 16) {
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
@ -363,15 +364,6 @@ public class AndroidConfigChooser implements EGLConfigChooser {
|
|||||||
private boolean inRange(int val, int min, int max) {
|
private boolean inRange(int val, int min, int max) {
|
||||||
return min <= val && val <= 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.
|
//DON'T REMOVE THIS, USED FOR UNIT TESTING FAILING CONFIGURATION LISTS.
|
||||||
// private static class Config {
|
// private static class Config {
|
||||||
|
@ -32,11 +32,15 @@
|
|||||||
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.graphics.PixelFormat;
|
||||||
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,16 +52,16 @@ 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.android.OGLESShaderRenderer;
|
import com.jme3.renderer.android.OGLESShaderRenderer;
|
||||||
|
import com.jme3.renderer.android.RendererUtil;
|
||||||
import com.jme3.system.*;
|
import com.jme3.system.*;
|
||||||
import com.jme3.system.android.AndroidConfigChooser.ConfigType;
|
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 {
|
||||||
@ -135,60 +139,60 @@ 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);
|
|
||||||
|
|
||||||
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.setEGLContextClientVersion(clientOpenGLESVersion);
|
||||||
view.setEGLConfigChooser(configChooser);
|
|
||||||
view.getHolder().setFormat(configChooser.getPixelFormat());
|
|
||||||
} finally {
|
|
||||||
if (display != null) {
|
|
||||||
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
|
// 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);
|
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);
|
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
|
||||||
@ -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();
|
timer = new AndroidTimer();
|
||||||
renderer = new OGLESShaderRenderer();
|
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) {
|
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…
x
Reference in New Issue
Block a user