java.lang.IllegalArgumentException: No config chosen異常


針對java.lang.IllegalArgumentException: No config chosen異常,網絡上流行的修改辦法是:

在游戲端,調用gLSurfaceView.setEGLConfigChooser(8 8, 8, 8, 16, 0)。

這樣修改,到底修改了什么,如何起作用的?下面分析下源碼,看看這個問題。

EGL 是 OpenGLES 和底層 Native 平台視窗系統之間的接口。對EGL的使用,一般是初始化后,選擇恰當的配置。

下面是選擇一個 EGL 配置的函數原型:

EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint * num_config);

參數 attrib_list 指定了選擇配置時需要參照的屬性。參數 configs 將返回一個按照 attrib_list 排序的平台有效的所有 EGL framebuffer 配置列表。參數 config_size 指定了可以返回到 configs 的總配置個數。參數 num_config 返回了實際匹配的配置總數。

1.異常發生的現場如下:

<BaseConfigChooser類>

 

public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
    int[] num_config = new int[1];
    //第一次調用eglChooseConfig獲取有效配置數,mConfigSpec為參考屬性,在構造函數中賦值
    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");
    }
    EGLConfig[] configs = new EGLConfig[numConfigs];
    //第二次調用eglChooseConfig獲取有效配置列表
    if (!egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs,
        num_config)) {
        throw new IllegalArgumentException("eglChooseConfig#2 failed");
    }
    //調用另一個重載的chooseConfig函數(為抽象方法,在子類中實現),根據給定的r,g,b,a,depth,stencil選擇EGL配置
    EGLConfig config = chooseConfig(egl, display, configs);
    if (config == null) {
        //拋出java.lang.IllegalArgumentException: No config chosen異常
        throw new IllegalArgumentException("No config chosen");  
    }
    return config;
}

 

     

2.下面來看看chooseConfig(egl, display, configs)何時會返回NULL

<ComponentSizeChooser類繼承自BaseConfigChooser>

 

private class ComponentSizeChooser extends BaseConfigChooser {
    //構造函數
    public ComponentSizeChooser(int redSize, int greenSize, int blueSize,
                int alphaSize, int depthSize, int stencilSize) {
            //構造父類,即BaseConfigChooser,設置對應的mConfigSpec
            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;
       }

    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;
        }

 

    

該函數遍歷所有配置,找到第一個滿足如下條件的配置:

①Depth和Stencil不小於給定值

②R,G,B,Alpha等於給定值

當沒有滿足上述條件的EGL配置時,返回NULL。

這些給定值從和而來?這就是setEGLConfigChooser的工作

 

3.setEGLConfigChooser都干了些啥

<GLSurfaceView類>

 

public void setEGLConfigChooser(int redSize, int greenSize, int blueSize, 

                                int alphaSize, int depthSize, int stencilSize) { 

    setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize, 

                            blueSize, alphaSize, depthSize, stencilSize)); 

} 

 

    

該函數根據給定的r,g,b,a,depth,stencil值創建ComponentSizeChooser實例。ComponentSizeChooser::chooseConfig函數會用到這些值。

 

從以上源碼可知,

調用gLSurfaceView.setEGLConfigChooser(8 8, 8, 8, 16, 0),

GLSurfaceView 將根據(r,g,b,a,depth,stencil)-(8 8, 8, 8, 16, 0)去選擇EGL配置。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM