diff options
Diffstat (limited to 'engine/src/android/com/jme3/system/android/AndroidConfigChooser.java')
-rw-r--r-- | engine/src/android/com/jme3/system/android/AndroidConfigChooser.java | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/engine/src/android/com/jme3/system/android/AndroidConfigChooser.java b/engine/src/android/com/jme3/system/android/AndroidConfigChooser.java new file mode 100644 index 0000000..e55fa55 --- /dev/null +++ b/engine/src/android/com/jme3/system/android/AndroidConfigChooser.java @@ -0,0 +1,362 @@ +package com.jme3.system.android; + +import android.graphics.PixelFormat; +import android.opengl.GLSurfaceView.EGLConfigChooser; +import java.util.logging.Logger; +import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.egl.EGLDisplay; + +/** + * AndroidConfigChooser is used to determine the best suited EGL Config + * @author larynx + * + */ +public class AndroidConfigChooser implements EGLConfigChooser +{ + private static final Logger logger = Logger.getLogger(AndroidConfigChooser.class.getName()); + + protected int clientOpenGLESVersion = 0; + protected EGLConfig bestConfig = null; + protected EGLConfig fastestConfig = null; + protected EGLConfig choosenConfig = null; + protected ConfigType type; + protected int pixelFormat; + + protected boolean verbose = false; + + private final static int EGL_OPENGL_ES2_BIT = 4; + + public enum ConfigType + { + /** + * RGB565, 0 alpha, 16 depth, 0 stencil + */ + FASTEST, + /** + * RGB???, 0 alpha, >=16 depth, 0 stencil + */ + BEST, + /** + * Turn off config chooser and use hardcoded + * setEGLContextClientVersion(2); + * setEGLConfigChooser(5, 6, 5, 0, 16, 0); + */ + LEGACY + } + + public AndroidConfigChooser(ConfigType type, boolean verbose) + { + this.type = type; + this.verbose = verbose; + } + + /** + * Gets called by the GLSurfaceView class to return the best config + */ + @Override + public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) + { + logger.info("GLSurfaceView asks for egl config, returning: "); + logEGLConfig(choosenConfig, display, egl); + return choosenConfig; + } + + /** + * findConfig is used to locate the best config and init the chooser with + * @param egl + * @param display + * @return true if successfull, false if no config was found + */ + public boolean findConfig(EGL10 egl, EGLDisplay display) + { + + if (type == ConfigType.BEST) + { + ComponentSizeChooser compChooser = new ComponentSizeChooser(8, 8, 8, 8, 32, 0); + choosenConfig = compChooser.chooseConfig(egl, display); + + if (choosenConfig == null) + { + compChooser = new ComponentSizeChooser(8, 8, 8, 0, 32, 0); + choosenConfig = compChooser.chooseConfig(egl, display); + if (choosenConfig == null) + { + compChooser = new ComponentSizeChooser(8, 8, 8, 8, 16, 0); + choosenConfig = compChooser.chooseConfig(egl, display); + if (choosenConfig == null) + { + compChooser = new ComponentSizeChooser(8, 8, 8, 0, 16, 0); + choosenConfig = compChooser.chooseConfig(egl, display); + } + } + } + + logger.info("JME3 using best EGL configuration available here: "); + } + else + { + ComponentSizeChooser compChooser = new ComponentSizeChooser(5, 6, 5, 0, 16, 0); + choosenConfig = compChooser.chooseConfig(egl, display); + logger.info("JME3 using fastest EGL configuration available here: "); + } + + if (choosenConfig != null) + { + logger.info("JME3 using choosen config: "); + logEGLConfig(choosenConfig, display, egl); + 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, nether 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]; + int result = PixelFormat.RGB_565; + + egl.eglGetConfigAttrib(display, conf, EGL10.EGL_RED_SIZE, value); + if (value[0] == 8) + { + result = PixelFormat.RGBA_8888; + /* + egl.eglGetConfigAttrib(display, conf, EGL10.EGL_ALPHA_SIZE, value); + if (value[0] == 8) + { + result = PixelFormat.RGBA_8888; + } + else + { + result = PixelFormat.RGB_888; + }*/ + } + + if (verbose) + { + logger.info("Using PixelFormat " + result); + } + + //return result; TODO Test pixelformat + return PixelFormat.TRANSPARENT; + } + + 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); + // Check if conf is OpenGL ES 2.0 + if ((value[0] & EGL_OPENGL_ES2_BIT) != 0) + { + result = 2; + } + + return result; + } + + /** + * log output with egl config details + * @param conf + * @param display + * @param egl + */ + public 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_GREEN_SIZE, value); + logger.info(String.format("EGL_GREEN_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_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] ) ); + + egl.eglGetConfigAttrib(display, conf, EGL10.EGL_SURFACE_TYPE, value); + logger.info(String.format("EGL_SURFACE_TYPE = %d", value[0] ) ); + } + + 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 boolean bClientOpenGLESVersionSet; + + public BaseConfigChooser(int[] configSpec) + { + bClientOpenGLESVersionSet = false; + mConfigSpec = filterConfigSpec(configSpec); + } + + public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) + { + int[] num_config = new int[1]; + if (!egl.eglChooseConfig(display, mConfigSpec, null, 0, + num_config)) { + throw new IllegalArgumentException("eglChooseConfig failed"); + } + + int numConfigs = num_config[0]; + + if (numConfigs <= 0) + { + //throw new IllegalArgumentException("No configs match configSpec"); + + return null; + } + + EGLConfig[] configs = new EGLConfig[numConfigs]; + if (!egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, + num_config)) { + throw new IllegalArgumentException("eglChooseConfig#2 failed"); + } + EGLConfig config = chooseConfig(egl, display, configs); + //if (config == null) { + // throw new IllegalArgumentException("No config chosen"); + //} + return config; + } + + abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, + EGLConfig[] configs); + + protected int[] mConfigSpec; + + private int[] filterConfigSpec(int[] configSpec) + { + if (bClientOpenGLESVersionSet == true) { + return configSpec; + } + /* We know none of the subclasses define EGL_RENDERABLE_TYPE. + * And we know the configSpec is well formed. + */ + int len = configSpec.length; + int[] newConfigSpec = new int[len + 2]; + System.arraycopy(configSpec, 0, newConfigSpec, 0, len-1); + newConfigSpec[len-1] = EGL10.EGL_RENDERABLE_TYPE; + newConfigSpec[len] = 4; /* EGL_OPENGL_ES2_BIT */ + newConfigSpec[len+1] = EGL10.EGL_NONE; + + bClientOpenGLESVersionSet = true; + + return newConfigSpec; + } + } + + /** + * Choose a configuration with exactly the specified r,g,b,a sizes, + * and at least the specified depth and stencil sizes. + */ + private class ComponentSizeChooser extends BaseConfigChooser + { + public ComponentSizeChooser(int redSize, int greenSize, int blueSize, + int alphaSize, int depthSize, int stencilSize) + { + super(new int[] { + EGL10.EGL_RED_SIZE, redSize, + EGL10.EGL_GREEN_SIZE, greenSize, + EGL10.EGL_BLUE_SIZE, blueSize, + EGL10.EGL_ALPHA_SIZE, alphaSize, + EGL10.EGL_DEPTH_SIZE, depthSize, + EGL10.EGL_STENCIL_SIZE, stencilSize, + EGL10.EGL_NONE}); + mValue = new int[1]; + mRedSize = redSize; + mGreenSize = greenSize; + mBlueSize = blueSize; + mAlphaSize = alphaSize; + mDepthSize = depthSize; + mStencilSize = stencilSize; + } + + @Override + public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs) + { + for (EGLConfig config : configs) + { + int d = findConfigAttrib(egl, display, config, + EGL10.EGL_DEPTH_SIZE, 0); + int s = findConfigAttrib(egl, display, config, + EGL10.EGL_STENCIL_SIZE, 0); + if ((d >= mDepthSize) && (s >= mStencilSize)) + { + 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); + if ((r == mRedSize) && (g == mGreenSize) + && (b == mBlueSize) && (a == mAlphaSize)) { + return config; + } + } + } + return null; + } + + 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; + } + + private int[] mValue; + // Subclasses can adjust these values: + protected int mRedSize; + protected int mGreenSize; + protected int mBlueSize; + protected int mAlphaSize; + protected int mDepthSize; + protected int mStencilSize; + } + + + + +} |