4

我正在尝试在 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 资源,但规范允许。被警告!

4

2 回答 2

1

这不是受支持的用例。它之前工作的事实对你来说只是运气,它可能在某些设备上失败。您可以通过在不同的窗口中渲染 2D 或 3D 内容来解决此问题,或者在位图中渲染 2D 内容,然后将其用作 GL 纹理等。

于 2012-01-06T19:17:41.507 回答
0

您可以从 OpenGL 切换到 CPU 渲染 ( ANativeWindow_lock),反之亦然,但您需要释放使用Surface的并从您的其他 API 中Surface.release()创建一个新的。SurfaceTexture

示例应用

于 2018-02-22T22:05:05.013 回答