java.lang.RuntimeException с EGLConfigChooser на PowerVR G6200
На устройствах, использующих графический процессор PowerVR G6200, таких как Sony Xperia M5 (E5603) и Xiaomi Redmi Note 3 (hennessy), создание EGL-контекста для рендеринга с OpenGL ES 2 завершается неудачно, хотя оно работает на всех других протестированных мной устройствах:
java.lang.RuntimeException:
at android.opengl.GLSurfaceView$EglHelper.throwEglException (GLSurfaceView.java:1233)
at android.opengl.GLSurfaceView$EglHelper.throwEglException (GLSurfaceView.java:1224)
at android.opengl.GLSurfaceView$EglHelper.start (GLSurfaceView.java:1074)
at android.opengl.GLSurfaceView$GLThread.guardedRun (GLSurfaceView.java:1447)
at android.opengl.GLSurfaceView$GLThread.run (GLSurfaceView.java:1286)
Выбор конфигурации реализован так:
class CustomEGLConfigChooser implements GLSurfaceView.EGLConfigChooser {
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
EGLConfig [] configs = new EGLConfig[1];
int [] num_config = new int[1];
int [] attrib_list = new int[] {
EGL10.EGL_RED_SIZE, 8,
EGL10.EGL_GREEN_SIZE, 8,
EGL10.EGL_BLUE_SIZE, 8,
EGL10.EGL_ALPHA_SIZE, 8,
EGL10.EGL_DEPTH_SIZE, 24,
EGL10.EGL_STENCIL_SIZE, 8,
EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT,
EGL10.EGL_NONE,
};
boolean res = egl.eglChooseConfig(display, attrib_list, configs, configs.length, num_config);
if (res && num_config[0] > 0) {
return configs[0];
}
return null;
}
}
Выбор конфига используется из GLSurfaceView
подкласс, как это:
public class GameView extends GLSurfaceView {
public GameView (Context context, ClientConfig clientConfig) {
super(context);
setEGLContextClientVersion(2);
setEGLConfigChooser(new CustomEGLConfigChooser());
}
}
1 ответ
Сравнивая список конфигураций EGL на устройстве, на котором работает этот код (конфигурации Nexus 5x EGL), с нерабочим устройством (конфигурации Xiaomi Redmi Note 3 EGL), я обнаружил, что, хотя есть совпадающие конфигурации, они отличаются одним свойством, а именно EGL_RENDERABLE_TYPE
,
Первая конфигурация Nexus 5x EGL, которая соответствует:
EGL_CONFIG_ID: 11
[...]
EGL_ALPHA_SIZE: 8
EGL_BLUE_SIZE: 8
EGL_GREEN_SIZE: 8
EGL_RED_SIZE: 8
EGL_DEPTH_SIZE: 24
EGL_STENCIL_SIZE: 8
[...]
EGL_RENDERABLE_TYPE: OpenGL_ES OpenGL_ES_2 (5)
Первый конфиг Xiaomi Redmi Note 3 EGL, который соответствует:
EGL_CONFIG_ID: 1
[...]
EGL_ALPHA_SIZE: 8
EGL_BLUE_SIZE: 8
EGL_GREEN_SIZE: 8
EGL_RED_SIZE: 8
EGL_DEPTH_SIZE: 24
EGL_STENCIL_SIZE: 8
[...]
EGL_RENDERABLE_TYPE: OpenGL_ES (1)
Обратите внимание, что Nexus 5x поддерживает EGL_RENDERABLE_TYPE
с EGL_OPENGL_ES2_BIT
(в дополнение к поддержке EGL_OPENGL_ES_BIT
с той же конфигурацией), так что нам просто повезло, что все конфиги на существующих устройствах поддерживали оба типа рендеринга.
Существует еще одна конфигурация для Xiaomi Redmi Note 3, которая поддерживает визуализируемый тип ES2, но это не первая конфигурация, которая соответствует:
EGL_CONFIG_ID: 23
[...]
EGL_ALPHA_SIZE: 8
EGL_BLUE_SIZE: 8
EGL_GREEN_SIZE: 8
EGL_RED_SIZE: 8
EGL_DEPTH_SIZE: 24
EGL_STENCIL_SIZE: 8
[...]
EGL_RENDERABLE_TYPE: OpenGL_ES_2 (4)
Попытка использовать первый (config ID 1) с контекстом рендеринга ES2, очевидно, не работает, потому что конфиг не поддерживает рендеринг ES2. Исправление состоит в том, чтобы явно запрашивать визуализируемый тип как часть средства выбора конфигурации EGL следующим образом, изменяя пример в вопросе следующим образом:
int [] attrib_list = new int[] {
EGL10.EGL_RED_SIZE, 8,
EGL10.EGL_GREEN_SIZE, 8,
EGL10.EGL_BLUE_SIZE, 8,
EGL10.EGL_ALPHA_SIZE, 8,
EGL10.EGL_DEPTH_SIZE, 24,
EGL10.EGL_STENCIL_SIZE, 8,
EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT,
EGL10.EGL_RENDERABLE_TYPE, EGL10. EGL_OPENGL_ES2_BIT,
EGL10.EGL_NONE,
};
Обратите внимание, что в случае, когда нужно запрашивать только значения глубины / трафарета RGBA +, другой вариант - использовать setEGLConfigChooser(int, int, int, int, int, int) вместо пользовательской реализации, и это позаботится о запрашивая EGL_RENDERABLE_TYPE
на основе значения, установленного в setEGLContextClientVersion()
,