Android EGL_BAD_CONFIG error,配置EGLConfigChooser

11 篇文章 0 订阅
1 篇文章 0 订阅

解决Android OpenGl 因 配置EGLConfigChooser 错误造成的 EGL_BAD_CONFIG error,导致打开摄像头后黑屏问题。

自动选择最好的EGLConfig。

        EGL10 egl = (EGL10) EGLContext.getEGL();
        EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);

        int[] version = new int[3];
        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(ConfigType.BEST);
            // Init chooser
            if (!configChooser.findConfig(egl, display)) {
                Log.e("yl","Unable to find suitable EGL config");
            }

            clientOpenGLESVersion = configChooser.getClientOpenGLESVersion();
            if (clientOpenGLESVersion < 2) {
           	 Log.e("yl","OpenGL ES 2.0 is not supported on this device");
           }
            // Requesting client version from GLSurfaceView which is extended by
            // AndroidInput.
            this.setEGLContextClientVersion(clientOpenGLESVersion);
            this.setEGLConfigChooser(configChooser);
        } finally {
            if (display != null) {
                egl.eglTerminate(display);
            }
        }

AndroidConfigChooser.java

import android.graphics.PixelFormat;
import android.opengl.GLSurfaceView.EGLConfigChooser;
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.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) {
        this.type = type;
    }
    /**
     * 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.log(Level.INFO, "Using PixelFormat {0}", 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 {
        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;
        
        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;
        }
    }
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值