PowerVR G6200上带有EGLConfigChooser的java.lang.RuntimeException
在使用PowerVR G6200 GPU的设备上,如索尼Xperia M5(E5603)和小米Redmi Note 3(轩尼诗),使用OpenGL ES 2创建用于渲染的EGL上下文失败,而在我测试过的所有其他设备上都可以工作:PowerVR G6200上带有EGLConfigChooser的java.lang.RuntimeException,java,android,opengl-es-2.0,glsurfaceview,egl,Java,Android,Opengl Es 2.0,Glsurfaceview,Egl,在使用PowerVR G6200 GPU的设备上,如索尼Xperia M5(E5603)和小米Redmi Note 3(轩尼诗),使用OpenGL ES 2创建用于渲染的EGL上下文失败,而在我测试过的所有其他设备上都可以工作: java.lang.RuntimeException: at android.opengl.GLSurfaceView$EglHelper.throwEglException (GLSurfaceView.java:1233) at android.openg
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;
}
}
public class GameView extends GLSurfaceView {
public GameView (Context context, ClientConfig clientConfig) {
super(context);
setEGLContextClientVersion(2);
setEGLConfigChooser(new CustomEGLConfigChooser());
}
}
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,
};
config chooser在GLSurfaceView
子类中使用,如下所示:
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;
}
}
public class GameView extends GLSurfaceView {
public GameView (Context context, ClientConfig clientConfig) {
super(context);
setEGLContextClientVersion(2);
setEGLConfigChooser(new CustomEGLConfigChooser());
}
}
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,
};
通过比较此代码工作的设备()上的EGL配置列表与非工作设备()上的EGL配置列表,我发现虽然存在匹配的配置,但它们在一个属性上有所不同,即
EGL\u RENDERABLE\u 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)
第一个小米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\u RENDERABLE\u TYPE
和EGL\u OPENGL\u ES2\u BIT
(此外还支持EGL\u OPENGL\u ES\u BIT
),因此我们很幸运,现有设备上的所有配置恰好都支持这两种可渲染类型
小米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)
尝试将第一个(配置ID 1)与ES2呈现上下文一起使用显然不起作用,因为配置不支持ES2呈现。修复方法是显式请求可渲染类型作为EGL配置选择器的一部分,如下所示,修改问题中的示例:
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;
}
}
public class GameView extends GLSurfaceView {
public GameView (Context context, ClientConfig clientConfig) {
super(context);
setEGLContextClientVersion(2);
setEGLConfigChooser(new CustomEGLConfigChooser());
}
}
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+深度/模具值的情况下,另一个选项是使用而不是自定义实现,这将考虑根据setEGLContextClientVersion()
中设置的值请求EGL\u RENDERABLE_TYPE