在ICS上使用eglCreateWindowSurface,并从2D切换到3D

时间:2012-01-06 18:25:48

标签: android android-4.0-ice-cream-sandwich nativewindow egl

我正在尝试在Android ICS上制作基于NDK的游戏。它在Honeycomb和Gingerbread上运行良好。

游戏使用一些2D渲染,一些3D渲染,在两个执行的不同阶段之间切换。 (由于第三方代码,这是不可协商的。)我们使用ANativeWindow_lock() / ANativeWindow_unlockAndPost()进行2D渲染,eglCreateWindowSurface() / gl*() / {{1}用于3D渲染。

在Honeycomb和Gingerbread这一切都很好。在ICS上,eglSwapBuffers()在日志中失败并显示以下消息:

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) 失败了,因为某些内容窗口打开了2D渲染,并且不会让我将其更改为3D而不会以某种方式首先释放曲面。但是,ANativeWindow API似乎没有任何明显的方法可以做到这一点。

有没有其他人遇到过这个问题,解决方案是什么?

更新

所以我改写了我的2D渲染代码,改为使用OpenGL原语(将backbuffer上传到纹理,通过一对三角形渲染纹理,交换缓冲区)。这很有用。 现在正在发生的事情是2D渲染工作正常;然后我破坏表面,创建一个新的表面以准备3D渲染,第二次调用eglCreateWindowSurface()失败。这一次,有:

eglCreateWindowSurface()

...它会引发E/SurfaceTexture( 1869): [com.fnord/com.fnord.MyActivity] connect: already connected (cur=1, req=1) 的EGL错误。

请注意,新表面是使用与旧属性完全相同的属性创建的。我甚至尝试确保在两次拨打AEGL_BAD_NATIVE_WINDOW之间拨打eglTerminate() / eglInitialize()

是否可以使用每个ANativeWindow一次?如果是这样,那么Khronos的EGL一致性测试是否会失败?有没有办法让NativeActivity重新创建窗口呢?

更新了更新

事实证明,最后一个问题是由于我在销毁上下文和曲面之前未能调用eglCreateWindowSurface()而导致的。这导致破坏被延迟,直到线程解除了上下文和表面,这当然不是,因此导致eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)的调用合法地失败(你不能有两个窗口表面原生窗口。)

这是 bit 违反直觉,因为人们会认为调用eglCreateWindowSurface()会破坏所有EGL资源,但规范允许这样做。请注意!

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

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

Example app