createWindowSurface 失败:EGL_BAD_MATCH? [英] createWindowSurface failed: EGL_BAD_MATCH?

查看:25
本文介绍了createWindowSurface 失败:EGL_BAD_MATCH?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

android 版本是 2.2.1 设备是三星 Galaxy II 完整的崩溃日志是:

the version android is 2.2.1 the device is a samsung galaxy II the full crash log is:

java.lang.RuntimeException: createWindowSurface failed: EGL_BAD_MATCH
at android.opengl.GLSurfaceView$EglHelper.throwEglException(GLSurfaceView.java:1077)
at android.opengl.GLSurfaceView$EglHelper.createSurface(GLSurfaceView.java:981)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1304)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1116)

这是崩溃的相关代码:

@Override 
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                         WindowManager.LayoutParams.FLAG_FULLSCREEN);
    glView = new GLSurfaceView(this);
    glView.setEGLConfigChooser(8 , 8, 8, 8, 16, 0);
    glView.setRenderer(this);
    setContentView(glView);
    \etc..............}

我使用了 setEGLConfigChooser(),因为如果应用程序不在 API-17 上,它会在 API-17 上崩溃,所以对于这个崩溃的特定设备,我一直在环顾四周,它与设备的 PixelFormat 有关.

i used setEGLConfigChooser() because the app would crash on API-17 if it wasnt in there so for this specific device that it is crashing on i been looking around and it has something to do with the PixelFormat for the device.

我想知道如何使用一些代码,这样它就不会在三星 Galaxy II android 版本 2.2.1 上崩溃,我无法在模拟器中测试它,我没有测试它的设备,我只需要确定代码,我不确定如何更改它?

What im wondering is how can i use some code so this will not crash on the samsung galaxy II android version 2.2.1, i cant test this in an emulator and i dont have the device to test it in, i just need for sure code and im not sure how to change it up?

推荐答案

更新: 我找到了解决这个问题的方法,实际上它相当简单.

Update: I found a way to work around this issue and actually it is fairly straightforward.

首先:Android默认的EGLConfigChooser 实施在某些方面做出了错误的决定设备.尤其是较旧的 Android 设备似乎遇到了这个 EGL_BAD_MATCH 问题.在调试过程中,我还发现那些较旧的麻烦制造者设备的可用 OpenGL ES 配置集非常有限.

First of all: Android's default EGLConfigChooser implementation makes bad decisions on some devices. Especially the older Android devices seem to suffer this EGL_BAD_MATCH issue. During my debugging sessions I also discovered that those older troublemaker devices had quite a limited set of available OpenGL ES configurations.

这个不匹配"问题的原因不仅仅是 GLSurfaceView 的像素格式和 OpenGL ES 的颜色位深度设置不匹配.总的来说,我们必须处理以下问题:

The cause of this "bad match" problem is more than just a mismatch between the GLSurfaceView's pixel format and the color bit depth settings of OpenGL ES. Overall we have to deal with the following issues:

  • OpenGL ES API 版本不匹配
  • 请求的目标表面类型不匹配
  • 请求的颜色位深度无法在表面视图上呈现

在解释 OpenGL ES API 时,Android 开发人员文档严重不足.因此,在 Khronos.org 上阅读原始文档很重要.特别是关于 eglChooseConfig 的文档页面在这里很有帮助.

The Android developer documentation is severely lacking when it comes to explaining the OpenGL ES API. It is therefore important to read the original documentation over at Khronos.org. Especially the doc page about eglChooseConfig is helpful here.

为了解决上述问题,您必须确保指定以下最低配置:

In order to remedy above listed problems you have to make sure to specify the following minimum configuration:

  • EGL_RENDERABLE_TYPE 必须与您使用的 OpenGL ES API 版本匹配.在 OpenGL ES 2.x 的可能情况下,您必须将该属性设置为 4(请参阅 egl.h)
  • EGL_SURFACE_TYPE 应该设置 EGL_WINDOW_BIT
  • EGL_RENDERABLE_TYPE must match the OpenGL ES API version you are using. In the likely case of OpenGL ES 2.x you must set that attribute to 4(see egl.h)
  • EGL_SURFACE_TYPE should have the EGL_WINDOW_BIT set

当然,您还想设置一个 OpenGL ES 上下文,为您提供正确的颜色、深度和模板缓冲区设置.

And of course you also want to set up an OpenGL ES context that provides you with the correct color, depth and stencil buffer settings.

不幸的是,不可能以直接的方式挑选这些配置选项.我们必须从任何给定设备上可用的任何内容中进行选择.这就是为什么有必要实现一个自定义 EGLConfigChooser,它会遍历可用配置集列表并选择最符合给定标准的最合适的配置集.

Unfortunately it is not possible to cherry-pick these configuration options in a straightforward way. We have to choose from whatever is available on any given device. That's why it is necessary to implement a custom EGLConfigChooser, that goes through the list of available configuration sets and picks the most suitable one that matches best the given criteria.

无论如何,我为这样的配置选择器准备了一个示例实现:

Anyway, I whipped up a sample implementation for such a config chooser:

public class MyConfigChooser implements EGLConfigChooser {
    final private static String TAG = "MyConfigChooser";

    // This constant is not defined in the Android API, so we need to do that here:
    final private static int EGL_OPENGL_ES2_BIT = 4;

    // Our minimum requirements for the graphics context
    private static int[] mMinimumSpec = {
            // We want OpenGL ES 2 (or set it to any other version you wish)
            EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,

            // We want to render to a window
            EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT,

            // We do not want a translucent window, otherwise the
            // home screen or activity in the background may shine through
            EGL10.EGL_TRANSPARENT_TYPE, EGL10.EGL_NONE, 

            // indicate that this list ends:
            EGL10.EGL_NONE
    };

    private int[] mValue = new int[1];
    protected int mAlphaSize;
    protected int mBlueSize;
    protected int mDepthSize;
    protected int mGreenSize;
    protected int mRedSize;
    protected int mStencilSize;

    /**
    * The constructor lets you specify your minimum pixel format,
    * depth and stencil buffer requirements.
    */
    public MyConfigChooser(int r, int g, int b, int a, int depth, int 
                        stencil) {
        mRedSize = r;
        mGreenSize = g;
        mBlueSize = b;
        mAlphaSize = a;
        mDepthSize = depth;
        mStencilSize = stencil;
    }

    @Override
    public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
        int[] arg = new int[1];
        egl.eglChooseConfig(display, mMinimumSpec, null, 0, arg);
        int numConfigs = arg[0];
        Log.i(TAG, "%d configurations available", numConfigs);

        if(numConfigs <= 0) {
            // Ooops... even the minimum spec is not available here
            return null;
        }

        EGLConfig[] configs = new EGLConfig[numConfigs];
        egl.eglChooseConfig(display, mMinimumSpec, configs,    
            numConfigs, arg);

        // Let's do the hard work now (see next method below)
        EGLConfig chosen = chooseConfig(egl, display, configs);

        if(chosen == null) {
            throw new RuntimeException(
                    "Could not find a matching configuration out of "
                            + configs.length + " available.", 
                configs);
        }

        // Success
        return chosen;
    }

   /**
    * This method iterates through the list of configurations that 
    * fulfill our minimum requirements and tries to pick one that matches best
    * our requested color, depth and stencil buffer requirements that were set using 
    * the constructor of this class.
    */
    public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
            EGLConfig[] configs) {
        EGLConfig bestMatch = null;
        int bestR = Integer.MAX_VALUE, bestG = Integer.MAX_VALUE, 
            bestB = Integer.MAX_VALUE, bestA = Integer.MAX_VALUE, 
            bestD = Integer.MAX_VALUE, bestS = Integer.MAX_VALUE;

        for(EGLConfig config : configs) {
            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);
            int d = findConfigAttrib(egl, display, config,
                    EGL10.EGL_DEPTH_SIZE, 0);
            int s = findConfigAttrib(egl, display, config,
                    EGL10.EGL_STENCIL_SIZE, 0);

            if(r <= bestR && g <= bestG && b <= bestB && a <= bestA
                    && d <= bestD && s <= bestS && r >= mRedSize
                    && g >= mGreenSize && b >= mBlueSize 
                    && a >= mAlphaSize && d >= mDepthSize 
                    && s >= mStencilSize) {
                bestR = r;
                bestG = g;
                bestB = b;
                bestA = a;
                bestD = d;
                bestS = s;
                bestMatch = config;
            }
        }

        return bestMatch;
    }

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

这篇关于createWindowSurface 失败:EGL_BAD_MATCH?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆