Ошибка 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 для устройства.

Что мне интересно, как я могу использовать какой-то код, так что это не сработает на samsung galaxy II android version 2.2.1, я не могу проверить это в эмуляторе, и у меня нет устройства для его проверки, мне просто нужно обязательно код И я не уверен, как его изменить?

Solutions Collecting From Web of "Ошибка createWindowSurface: EGL_BAD_MATCH?"

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

Прежде всего: реализация EGLConfigChooser по умолчанию для 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'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; } } 

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

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

Усиление их ответа состоит в том, что вы можете получить желаемый пиксельный формат для окна и использовать его для динамического выбора контекста 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.

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