Подтвердить что ты не робот

Ошибка createWindowSurface: EGL_BAD_MATCH?

версия android 2.2.1 устройство является галактикой samsung II, полный журнал аварий:

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, если оно там не было, поэтому для этого конкретного устройства он рушится, когда я смотрю вокруг, и это имеет какое-то отношение к PixelFormat для устройства.

Что мне интересно, как я могу использовать какой-то код, так что это не сбой на галактике Android 2.2 версии 2.2.1, я не могу проверить это в эмуляторе, и у меня нет устройства для его проверки, мне просто нужно наверняка код и я не уверен, как его изменить?

4b9b3361

Ответ 1

Обновление: Я нашел способ обойти эту проблему, и на самом деле это довольно просто.

Прежде всего: Android по умолчанию EGLConfigChooser реализация принимает плохие решения по некоторым устройства. Особенно старые устройства Android, похоже, страдают от этой проблемы EGL_BAD_MATCH. Во время сеансов моей отладки я также обнаружил, что у этих более старых устройств с нарушениями правил был довольно ограниченный набор доступных конфигураций OpenGL ES.

Причиной этой проблемы "плохого совпадения" является не только несоответствие между пиксельным форматом GLSurfaceView и настройками глубины цветовой разрядности OpenGL ES. В целом мы имеем дело со следующими проблемами:

  • Несоответствие версии OpenGL ES API
  • Несоответствие запрошенного типа целевой поверхности
  • Запрошенная глубина цвета изображения не может быть отображена на вид поверхности

Документация разработчика Android сильно отсутствует, когда дело доходит до объяснения API OpenGL ES. Поэтому важно прочитать оригинальную документацию на Khronos.org. Особенно полезен документ doc о eglChooseConfig.

Чтобы устранить перечисленные выше проблемы, вы должны указать следующую минимальную конфигурацию:

  • EGL_RENDERABLE_TYPE должен соответствовать используемой версии OpenGL ES API. В вероятном случае OpenGL ES 2.x вы должны установить этот атрибут в 4 (см. egl.h)
  • EGL_SURFACE_TYPE должен иметь EGL_WINDOW_BIT установить

И, конечно же, вы также хотите настроить контекст OpenGL ES, который предоставляет вам правильные настройки буфера цвета, глубины и трафарета.

К сожалению, невозможно использовать эти параметры конфигурации в прямом режиме. Мы должны выбирать из того, что доступно на любом устройстве. Для этого необходимо реализовать пользовательский EGLConfigChooser, который проходит через список доступных наборов конфигураций и выбирает наиболее подходящий, который соответствует лучшим данные критерии.

В любом случае, я выбрал примерную реализацию для такого конфигурационного выбора:

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

Ответ 2

У меня нет оценки репутации, чтобы добавить комментарий, иначе я бы поместил краткий комментарий на ответ Nobu Games. Я столкнулся с той же ошибкой EGL_BAD_MATCH, и их ответ помог мне на правильном пути. Вместо этого мне нужно создать отдельный ответ.

Как упоминает Nobu Games, между GLSurfaceView PixelFormat и параметрами формата пикселя, переданными в setEGLConfigChooser(), возникает несоответствие. В моем случае я просил RGBA8888, но мой GLSurfaceView был RGB565. Это вызвало ошибку EGL_BAD_MATCH позже в моей инициализации.

Усиление их ответа состоит в том, что вы можете получить нужный PixelFormat для окна и использовать его для динамического выбора контекста EGL.

Чтобы сделать мой код как можно более общим, я изменил GLSurfaceView, чтобы взять дополнительный параметр - формат пикселя дисплея. Я получаю это от своей деятельности, позвонив:

getWindowManager().getDefaultDisplay().getPixelFormat();

Я передаю это значение в GLSurfaceView и затем извлекаю оптимальные битовые глубины для каждого из RGBA следующим образом:

if (pixelFormatVal > 0) {

    PixelFormat info = new PixelFormat();
    PixelFormat.getPixelFormatInfo(pixelFormatVal, info);

    if (PixelFormat.formatHasAlpha(pixelFormatVal)) {

        if (info.bitsPerPixel >= 24) {
            m_desiredABits = 8;
        } else {
            m_desiredABits = 6;  // total guess
        }

    } else {
        m_desiredABits = 0;
    }

    if (info.bitsPerPixel >= 24) {
        m_desiredRBits = 8;
        m_desiredGBits = 8;
        m_desiredBBits = 8;
    } else if (info.bitsPerPixel >= 16) {
        m_desiredRBits = 5;
        m_desiredGBits = 6;
        m_desiredRBits = 5;
    } else {
        m_desiredRBits = 4;
        m_desiredGBits = 4;
        m_desiredBBits = 4;
    }

} else {
    m_desiredRBits = 8;
    m_desiredGBits = 8;
    m_desiredBBits = 8;
}

Затем передаю эти значения до моего конфигурационного выбора. Этот код работает для меня на устройстве RGB565, а также в устройстве RGBA8888.

Мое предположение заключается в том, что поставщик выбрал по умолчанию причину и что он даст самые результативные результаты. Конечно, мне нечем поддержать этот отчет, но это стратегия, с которой я иду.