我正在尝试在 Android ICS 上制作基于 NDK 的游戏。它在 Honeycomb 和 Gingerbread 上运行良好。
游戏使用一些 2D 渲染,一些 3D 渲染,在执行的不同阶段在两者之间切换。(由于第三方代码,这是不可协商的。)我们使用ANativeWindow_lock()
/ANativeWindow_unlockAndPost()
进行 2D 渲染,而eglCreateWindowSurface()
/ gl*()
/eglSwapBuffers()
用于 3D 渲染。
在 Honeycomb 和 Gingerbread 上,这一切都很好。在 ICS 上,eglCreateWindowSurface()
失败并在日志中显示以下消息:
E/SurfaceTexture( 1765): [com.fnord/com.fnord.MyActivity] connect: already connected (cur=2, req=1)
E/libEGL ( 5466): EGLNativeWindowType 0x29e9b8 already connected to another API
E/libEGL ( 5466): eglCreateWindowSurface:374 error 300b (EGL_BAD_NATIVE_WINDOW)
E/libEGL ( 5466): call to OpenGL ES API with no current context (logged once per thread)
查看源代码似乎很明显eglCreateWindowSurface()
失败了,因为有些东西打开了本机窗口以进行 2D 渲染,并且它不会让我在不首先释放表面的情况下将其更改为 3D。但是,ANativeWindow API 似乎没有任何明显的方法可以做到这一点。
有没有其他人遇到过这个问题,解决方案是什么?
更新
因此,我重写了我的 2D 渲染代码以改用 OpenGL 基元(将后缓冲区上传到纹理,通过一对三角形渲染纹理,交换缓冲区)。这在一定程度上起作用。现在发生的事情是 2D 渲染工作正常;然后我破坏了表面,创建了一个新的表面以准备 3D 渲染,第二次调用eglCreateWindowSurface()
失败。这一次,与:
E/SurfaceTexture( 1869): [com.fnord/com.fnord.MyActivity] connect: already connected (cur=1, req=1)
...它会引发 EGL 错误AEGL_BAD_NATIVE_WINDOW
。
请注意,新曲面的创建属性与旧曲面完全相同。我什至尝试确保在两次调用之间调用eglTerminate()
/ 。eglInitialize()
eglCreateWindowSurface()
我可以精确地使用每个 ANativeWindow 一次吗?如果是这样,那难道不会通过 Khronos 的 EGL 一致性测试吗?那么有没有办法让 NativeActivity 重新创建窗口呢?
更新更新
eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)
事实证明,最后一个问题是由于我在破坏上下文和表面之前未能调用造成的。这导致破坏被延迟,直到线程解除上下文和表面的绑定,当然不是,因此导致调用eglCreateWindowSurface()
合法失败(您不能在同一个本机窗口上有两个窗口表面)。
这有点违反直觉,因为人们会假设调用eglTerminate()
会破坏所有 EGL 资源,但规范允许。被警告!