CreateWindowSurface ha fallado: EGL_BAD_MATCH?

La versión de Android es 2.2.1 el dispositivo es una galaxia samsung II el registro de bloqueo completo es:

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) 

Este es el código relevante para el accidente:

 @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..............} 

He utilizado setEGLConfigChooser () porque la aplicación se bloquearía en API-17 si no estaba allí por lo que para este dispositivo específico que se está estrellando en que he estado buscando y tiene algo que ver con el PixelFormat para el dispositivo.

Lo que me estoy preguntando es cómo puedo usar algún código para que esto no se bloquee en la galaxia samsung II versión 2.2.1 android, no puedo probar esto en un emulador y no tengo el dispositivo para probarlo, sólo necesito seguro de código Y no estoy seguro de cómo cambiarlo?

Actualización: he encontrado una manera de evitar este problema y en realidad es bastante sencillo.

En primer lugar: la implementación por defecto de EGLConfigChooser Android toma malas decisiones en algunos dispositivos. Especialmente los dispositivos Android más antiguos parecen sufrir este problema EGL_BAD_MATCH . Durante mis sesiones de depuración también descubrí que aquellos dispositivos más antiguos de perturbadores tenían un conjunto bastante limitado de configuraciones de OpenGL ES disponibles.

La causa de este problema de "coincidencia incorrecta" es más que un simple desajuste entre el formato de píxeles de GLSurfaceView y la configuración de profundidad de bits de color de OpenGL ES. En general, tenemos que lidiar con los siguientes temas:

  • Un desajuste de la versión de la API de OpenGL ES
  • Un desajuste del tipo de superficie objetivo solicitado
  • La profundidad de bits de color solicitada no se puede representar en la vista de la superficie

La documentación del desarrollador de Android es muy escasa cuando se trata de explicar la API de OpenGL ES. Por lo tanto, es importante leer la documentación original en Khronos.org. Especialmente la página doc sobre eglChooseConfig es útil aquí.

Para solucionar los problemas mencionados anteriormente, debe asegurarse de especificar la siguiente configuración mínima:

  • EGL_RENDERABLE_TYPE debe coincidir con la versión de la API de OpenGL ES que está utilizando. En el caso probable de OpenGL ES 2.x debe establecer ese atributo en 4 (consulte egl.h )
  • EGL_SURFACE_TYPE debe tener el conjunto EGL_WINDOW_BIT

Y, por supuesto, también desea configurar un contexto de OpenGL ES que le proporcione el color correcto, la profundidad y la configuración del búfer de plantilla.

Desafortunadamente, no es posible seleccionar estas opciones de configuración de una manera sencilla. Tenemos que elegir entre lo que esté disponible en cualquier dispositivo. Es por eso que es necesario implementar un EGLConfigChooser personalizado, que pasa a través de la lista de conjuntos de configuración disponibles y selecciona el más adecuado que coincida con los mejores criterios.

De todos modos, me preparó una implementación de ejemplo para tal config selector:

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

No tengo el puntaje de la reputación para agregar un comentario todavía, o bien habría puesto un breve comentario sobre la respuesta de Nobu Games. Encontré este mismo error EGL_BAD_MATCH y su respuesta me ayudó a ponerme en el camino correcto. En su lugar, tengo que crear una respuesta separada.

Como menciona Nobu Games, parece haber un desajuste entre el PixelFormat de GLSurfaceView y los parámetros de formato de píxeles pasados ​​a setEGLConfigChooser() . En mi caso, pedía RGBA8888 pero mi GLSurfaceView era RGB565. Esto causó el error EGL_BAD_MATCH más adelante en mi inicialización.

La mejora de su respuesta es que puede obtener el PixelFormat deseado para la ventana y utilizarlo para elegir dinámicamente un contexto EGL.

Para hacer mi código tan genérico como sea posible, cambié el GLSurfaceView para tomar en un parámetro adicional – el formato del pixel de la exhibición. Recibo esto de mi actividad llamando a:

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

Paso este valor hasta el GLSurfaceView y luego extraer las profundidades de bits óptima para cada uno de RGBA como este:

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

A continuación, pasar estos valores a mi config selector. Este código funciona para mí en un dispositivo RGB565, así como un dispositivo RGBA8888.

Mi suposición es que el vendedor ha elegido el defecto por una razón y que dará los resultados más eficaces. Por supuesto que no tengo nada para respaldar esa declaración, pero es la estrategia que voy a seguir.

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.