虽然有很多关于在Android上使用OpenGL ES的示例,但它们似乎都存在问题(即使是与Android SDK / NDK一起提供的示例),涉及EGL的初始化/终止过程。问题源自于Android应用程序模型,这使得正确使用EGL变得奇怪。
真正的问题在于,EGL是针对操作系统的进程进行初始化的,而所有的Android示例,甚至GLSurfaceView(实际上大多数示例都使用它)都涉及EGL的按组件(Activity或WallpaperService)初始化/终止。这完全是错误的,因为所有组件都在同一个进程中运行!如果应用只包含一个组件,则没有问题,但如果应用中有多个组件,并且它们都使用OpenGL ES,则这是一个问题。
考虑以下情况:两个使用OpenGL ES的应用程序组件同时运行,其中一个完成了。在完成此类组件时,将调用eglTerminate()(请查看GLSurfaceView源代码,以了解我所说的内容),这将终止整个进程的EGL!从此时开始,另一个已经运行的组件的任何EGL调用都将失败!
我检查了许多示例,它们都是以每个组件为基础初始化和终止EGL(实际上我看到的没有一个人做出了与GLSurfaceView不同的事情,大多数示例只是复制了GLSurfaceView的内部机制)。
现在,我想找到一种“正确”的方法,在Android上使用EGL。
这种“正确”的方式应该提供:
- 当任何第一个使用EGL的组件启动时,进行EGL初始化
- 当最后一个使用EGL的组件完成时,进行EGL终止
- 多线程。不应该限制仅能从主应用程序线程进行EGL操作。
请注意,(2)对于最小化没有使用EGL/OpenGL ES的活动实体时,是必要的来最小化系统资源的使用。
有什么想法吗?或者我在Android上忽略了一些EGL相关的内容吗?
更新
还有一个有趣的相关问题:
由于每个线程只允许一个活动渲染上下文,因此同一时间只能有一个组件使用主线程上的OpenGL ES。主线程同时运行多个使用OpenGL ES的组件会导致问题,因为最后一个调用eglMakeCurrent()的组件将隐含地“替换”所有其他组件的上下文,从而完全破坏组件逻辑。
更新2(最终)
据Romain Guy透露,Android实际上有一种内部解决EGL初始化/终止问题的方法,即在eglInitialize()和eglTerminate()中采用显式的“引用计数”方式(这违反了EGL规范,也没有在Android文档中提到)。