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



我正在尝试让一款基于NDK的游戏在Android ICS上运行。它在蜂窝和姜饼上效果很好。

游戏使用一些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基元(将backbuffer上传到纹理,通过一对三角形渲染纹理,swapbuffer)。这在一定程度上起作用现在发生的事情是2D渲染工作正常;然后我破坏了曲面,创建了一个新曲面,为3D渲染做准备,对eglCreateWindowSurface()的第二次调用失败。这次,使用:

E/SurfaceTexture( 1869): [com.fnord/com.fnord.MyActivity] connect: already connected (cur=1, req=1)

并且它抛出CCD_ 9的EGL错误。

请注意,创建的新曲面具有与旧曲面完全相同的属性。我甚至试着确保在对eglCreateWindowSurface()的两次调用之间调用eglTerminate()/eglInitialize()

我可以精确地使用每个ANativeWindow一次吗?如果是这样的话,这难道不会通过Khronos的EGL一致性测试吗?那么,有没有办法让NativeActivity重新创建窗口?

更新更新

事实证明,最后一个问题是由于我未能在破坏上下文和表面之前调用eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)。这导致破坏被延迟,直到线程解除上下文和表面的绑定,当然不是这样,所以导致对eglCreateWindowSurface()的调用合法失败(在同一个本地窗口上不能有两个窗口表面)。

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

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

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

示例应用

相关内容

  • 没有找到相关文章

最新更新