为什么eglMakeCurrent()调用失败并出现EGL_BAD_MATCH错误?

20

我正在使用OpenGL/EGL为Android开发应用程序。我的应用程序需要第二个上下文来从第二个线程加载纹理。

我的代码在Android 2.3上运行良好,但是当我尝试在4.0.3的Android设备或模拟器上运行代码时,eglMakeCurrent()会失败并显示EGL_BAD_MATCH错误。

第二个上下文及其像素缓冲区的初始化也都正常工作,所以我不确定从哪里开始寻找这个错误。

以下是初始化代码:

ANativeWindow *window = (ANativeWindow*)displaySurface;

EGLint dummy, format;

display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

eglInitialize(display, 0, 0);

EGLint contextAttribs[] =
{
    EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE
};

const EGLint configAttribs[] =
{
    EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
    EGL_BLUE_SIZE, 8,
    EGL_GREEN_SIZE, 8,
    EGL_RED_SIZE, 8,
    EGL_ALPHA_SIZE, 8,
    EGL_BUFFER_SIZE, 32,
    EGL_DEPTH_SIZE, 24,
    EGL_NONE
};

EGLint numConfigs;
EGLConfig config;

eglChooseConfig(display, configAttribs, &config, 1, &numConfigs);
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
ANativeWindow_setBuffersGeometry(window, 0, 0, format);

surface = eglCreateWindowSurface(display, config, window, NULL);
if(surface == NULL)
    Trace("error creating window surface: " + GetEglError());

context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
if(context == NULL)
    Trace("error creating main context: " + GetEglError());

const EGLint auxConfigAttribs[] =
{
    EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
    EGL_BLUE_SIZE, 8,
    EGL_GREEN_SIZE, 8,
    EGL_RED_SIZE, 8,
    EGL_ALPHA_SIZE, 8,
    EGL_DEPTH_SIZE, 0,
    EGL_STENCIL_SIZE, 0,
    EGL_NONE
};

EGLint pbufferAttribs[] =
{
    EGL_WIDTH, 1,
    EGL_HEIGHT, 1,
    EGL_TEXTURE_TARGET, EGL_NO_TEXTURE,
    EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE,
    EGL_NONE
};

EGLint auxNumConfigs;
EGLConfig auxConfig;

eglChooseConfig(display, auxConfigAttribs, &auxConfig, 1, &auxNumConfigs);

auxSurface = eglCreatePbufferSurface(display, auxConfig, pbufferAttribs);
if(auxSurface == NULL)
    Trace("error creating pbuffer surface: " + GetEglError());

auxContext = eglCreateContext(display, auxConfig, context, contextAttribs);
if(auxSurface == NULL)
    Trace("error creating auxilliary context: " + GetEglError());

if(!eglMakeCurrent(display, surface, surface, context))
    Trace("could not make main context current: " + GetEglError());

在我的Android 2.3设备(HTC Desire)上,上述初始化代码可以完美地工作,我可以让auxContext处于当前状态,并成功加载纹理。

但是,在我的Android 4.0.3设备(Samsung Nexus S)和Android 4.1设备(Galaxy Note 2)上,eglMakeCurrent()在成功初始化后会出现EGL_BAD_MATCH错误。

有人知道我可能为什么会遇到这个错误吗?


1
我注意到有时在Galaxy S2上调用eglMakeCurrent时会出现EGL_BAD_MATCH错误。我相信我已经将错误条件缩小到:a)在不同的线程上创建上下文,而不是使其成为当前线程;或者b)在第二个线程上使上下文成为当前线程,而没有从第一个线程中释放它。 - nmr
请查看标记答案的评论以获取解决方案。 - CuriousGeorge
3个回答

12

啊,这是我实际了解的事情。 ;) [我花费了五年时间在各种EGL实现上工作]。

我非常确定您的surface与实际显示表面的格式不同。我不确定差异是什么,或者您需要更改什么。也许需要修改EGL_DEPTH_SIZE?您可以尝试枚举可用的模式,看看是否有任何“可能”的选项。我知道,这有点麻烦,但我以前也多次遇到过这种情况 - 不同之处在于我通常可以查看EGL源代码并弄清楚我做错了什么...... ;)


问题是,makeCurrent() 在所有手机的主上下文中都可以正常工作,但在其他两个手机的第二/共享上下文中无法正常工作。然而,我发现了一篇帖子,也建议像你说的那样做:http://stackoverflow.com/questions/7523597/egl-bad-match-with-droid-droid-2 - 我可能会得到与 surface 请求不同的配置,但是使用 请求的 配置而不是 返回的 配置创建像素缓冲区,这可能是批处理匹配的原因。 - CuriousGeorge
2
是的,完全有可能在一个、两个、五个或十六个手机上运行良好,但在另外一两个手机上失败。曾经我负责测试某型号硬件的EGL驱动程序,该硬件使用了与我们其他可用硬件不同的EGL配置集。因此,每当测试套件引入新的测试时,它几乎肯定会在我的硬件上出现故障,但在其他所有硬件上都能正常工作。然后就面临着找到“适用于所有平台的好折衷方案”的挑战——或者添加一些代码来处理“如果我们有X型号硬件,则执行此操作,否则执行那个操作”的情况。 - Mats Petersson
6
我尝试罗列所有配置,得出了两个发现。首先,几乎所有支持EGL_WINDOW_BIT的显示配置也支持EGL_PBUFFER_BIT,这使得创建两个单独的配置完全没有意义。第二件事是,eglChooseConfig在所有android设备/版本上似乎都不能正常工作。这可能是设计上的问题,因为这在一个没有GPU支持的模拟器上发生了,但我获得的配置甚至都不符合我输入的规格。所以我写了自己的eglChooseConfig,并对两个表面使用了相同的配置,现在一切都正常了。 - CuriousGeorge
@bitwise,你能分享一下 eglChooseConfig 的实现吗? - Jerikc XIONG
2
@Jerikc 我已经很久没有使用这段代码了,所以我不能保证它能够满足你的需求,更不用说能否正常工作了,但是这里是它的链接 :) - http://ideone.com/etNRSW - CuriousGeorge
@MatsPetersson 你能否请看一下 https://stackoverflow.com/questions/64087683/android-opengl-stuff-doesnt-work-on-some-devices-eglmakecurrent-failed-and-gld 这个链接?类似的问题,也涉及特定设备。 - user924

6
如果您遇到此错误,但未涉及此表面或纹理内容,请转到运行并键入.android,然后转到AVD和当前的模拟器,删除用户数据文件,通常在.img文件上,重新启动模拟器,然后进行测试。这对我有用,如果在设备上测试时出现此问题,请清除数据并重新启动应用程序。祝愿那些发现此信息有用的人。

13
是的,我知道,但出于某种原因,这个错误也发生在了我的电脑上,而被接受的答案对我的情况并没有帮助。后来我解决了它并发布了这篇文章。所以如果其他人遇到类似的错误,它们可能会很有用。 - ralphgabb

1

确保你已经在传入eglChooseConfig()调用的属性中为EGL_SURFACE_TYPE设置了EGL_PBUFFER_BIT。这对我很有帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接