java.lang.RuntimeException 在 PowerVR G6200 上使用 EGLConfigChooser
java.lang.RuntimeException with EGLConfigChooser on PowerVR G6200
在使用 PowerVR G6200 GPU 的设备上,例如 Sony Xperia M5 (E5603) 和小米 Redmi Note 3 (hennessy),创建用于使用 OpenGL ES 2 渲染的 EGL 上下文失败,而它适用于所有其他设备 I已测试:
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());
}
}
通过比较运行此代码的设备上的 EGL 配置列表 (Nexus 5x EGL configs) with a non-working device (Xiaomi Redmi Note 3 EGL configs),我发现虽然有匹配的配置,但它们有一个 属性 不同,即 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)
首先匹配的小米红米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
),所以我们很幸运,现有设备恰好支持这两种可渲染类型。
小米红米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)
尝试将第一个(配置 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 + depth/stencil 值的情况下,另一种选择是使用 setEGLConfigChooser(int, int, int, int, int, int) 而不是自定义实现,这将负责请求EGL_RENDERABLE_TYPE
基于 setEGLContextClientVersion()
.
中设置的值
在使用 PowerVR G6200 GPU 的设备上,例如 Sony Xperia M5 (E5603) 和小米 Redmi Note 3 (hennessy),创建用于使用 OpenGL ES 2 渲染的 EGL 上下文失败,而它适用于所有其他设备 I已测试:
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());
}
}
通过比较运行此代码的设备上的 EGL 配置列表 (Nexus 5x EGL configs) with a non-working device (Xiaomi Redmi Note 3 EGL configs),我发现虽然有匹配的配置,但它们有一个 属性 不同,即 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)
首先匹配的小米红米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
),所以我们很幸运,现有设备恰好支持这两种可渲染类型。
小米红米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)
尝试将第一个(配置 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 + depth/stencil 值的情况下,另一种选择是使用 setEGLConfigChooser(int, int, int, int, int, int) 而不是自定义实现,这将负责请求EGL_RENDERABLE_TYPE
基于 setEGLContextClientVersion()
.