Android CreateWindowsSurface失败:EGL\u错误\u匹配?
android版本为2.2.1。该设备为三星galaxy II。完整的崩溃日志为:Android CreateWindowsSurface失败:EGL\u错误\u匹配?,android,crash,egl,Android,Crash,Egl,android版本为2.2.1。该设备为三星galaxy II。完整的崩溃日志为: java.lang.RuntimeException: createWindowSurface failed: EGL_BAD_MATCH at android.opengl.GLSurfaceView$EglHelper.throwEglException(GLSurfaceView.java:1077) at android.opengl.GLSurfaceView$EglHelper.createSurfa
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上,它会在API-17上崩溃,所以对于这个正在崩溃的特定设备,我一直在四处寻找,它与设备的像素格式有关
我想知道的是,我如何使用一些代码,这样就不会在三星galaxy II android 2.2.1版上崩溃,我无法在模拟器中测试,我也没有设备来测试它,我只需要确定代码,但我不确定如何更改它?更新:我找到了一种解决此问题的方法,实际上非常简单 首先:Android的默认实现在某些方面做出了错误的决定 设备。尤其是较旧的安卓设备似乎遇到了这一问题。在调试过程中,我还发现那些较旧的麻烦制造器设备的可用OpenGL ES配置非常有限 “不匹配”问题的原因不仅仅是GLSURFACHEVIEW的像素格式与OpenGL ES的颜色位深度设置不匹配。总的来说,我们必须处理以下问题:
- OpenGL ES API版本不匹配
- 请求的目标曲面类型不匹配
- 无法在曲面视图上渲染请求的颜色位深度
必须与您使用的OpenGL ES API版本相匹配。在OpenGL ES 2.x的可能情况下,必须将该属性设置为EGL\u RENDERABLE\u TYPE
(请参阅)4
应设置EGL\u表面类型
EGL\u窗口位
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;
}
}
公共类MyConfigChooser实现EGLConfigChooser{
最终私有静态字符串TAG=“MyConfigChooser”;
//Android API中未定义此常量,因此我们需要在此处执行此操作:
最终私有静态int EGL_OPENGL_ES2_位=4;
//我们对图形环境的最低要求
私有静态int[]mMinimumSpec={
//我们需要OpenGL ES 2(或将其设置为您希望的任何其他版本)
EGL10.EGL_可渲染类型,EGL_OPENGL_ES2_位,
//我们要渲染到一个窗口
EGL10.EGL_表面类型,EGL10.EGL_窗口位,
//我们不想要半透明的窗口,否则
//主屏幕或背景中的活动可能会闪烁
EGL10.EGL_透明_类型,EGL10.EGL_无,
//表示此列表结束:
EGL10.EGL_无
};
私有int[]mValue=新int[1];
相位不一致;
受保护的内部尺寸;
受保护的int-mDepthSize;
受保护的整数大小;
受保护的int-mRedSize;
受保护的整数大小;
/**
*构造函数允许您指定最小像素格式,
*深度和模具缓冲要求。
*/
公共MyConfigChooser(整数r、整数g、整数b、整数a、整数深度、整数
模板){
mRedSize=r;
mGreenSize=g;
mBlueSize=b;
相位错位=a;
mDepthSize=深度;
mStencilSize=模板;
}
@凌驾
公共egl配置选择配置(EGL10 egl,egl显示){
int[]arg=新的int[1];
egl.eglChooseConfig(display,mMinimumSpec,null,0,arg);
int numconfig=arg[0];
Log.i(标记“%d个可用配置”,numconfig);
如果(numConfigs我还没有声誉评分来添加评论,否则我会对Nobu Games的答案发表简短评论。我遇到了同样的EGL_BAD_匹配错误,他们的答案帮助我走上了正确的道路。相反,我必须创建一个单独的答案
正如Nobu Games提到的,GLSurfaceView的像素格式和传递给setEGLConfigChooser()
的像素格式参数之间似乎不匹配。在我的例子中,我要求的是RGBA8888,但我的GLSurfaceView是RGB565。这导致了后来在初始化过程中出现的EGL_BAD_匹配错误
对他们的答案的改进是,您可以获得窗口所需的像素格式,并使用它动态选择EGL上下文
为了使我的代码尽可能通用,我更改了GLSURFACHEVIEW以引入一个附加参数——显示器的像素格式。我通过调用以下命令从我的活动中获取此参数:
getWindowManager().getDefaultDisplay().getPixelFormat();
我将此值向下传递到GLSURFACHEVIEW,然后提取每个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设备和RGBA888设备
我的假设是,供应商选择默认值是有原因的,它将提供最有效的结果。当然,我没有什么可以支持这一说法,但这是我要采用的策略。感谢您提供的详细答案!这看起来很有希望,但不幸的是,它没有