我正在编写一个使用OpenGL ES(GLSurfaceView和GLSurfaceView.Renderer)的Android应用程序。问题是当用户切换应用程序然后切换回我的应用程序时,GLSurfaceView会破坏并重新创建GL上下文。这是根据文档应该做的,但有没有办法防止这种情况发生?
将纹理加载到上下文中需要很长时间,我希望不必重新加载它们。
答案 0 :(得分:15)
我认为您正在寻找的内容在GLSurfaceView文档中进行了讨论:
必须在通知时通知GLSurfaceView 活动暂停并恢复。 需要GLSurfaceView客户端 当活动时调用onPause() 暂停和onResume()时 活动恢复。这些电话允许 GLSurfaceView暂停和恢复 渲染线程,也允许 GLSurfaceView发布和重新创建 OpenGL显示。
使用标准Android SDK时,必须在暂停/恢复活动时释放/重新创建上下文(包括屏幕方向更改)。不执行此操作将导致GL上下文被释放,并且在活动被加载回内存时不会恢复。请记住,我们正在处理非常有限的资源(特别是在低规格设备上)。所以简短的回答是:你不能在不破坏你的应用程序的情况下阻止它。
假设您使用的是标准Android / OpenGL框架,则需要执行以下操作...
在您的活动中,请确保您拥有以下已覆盖的方法:
public void onPause() {
myGlSurfaceView.onPause();
}
public void onResume() {
myGlSurfaceView.onResume();
}
你在GL环境之外持有的任何东西仍然需要手动保存和恢复(位图,游戏状态等),因为你需要使用静态字段或像SharedPreferences这样的机制。
Android 3.x为preserve the GL context on pause提供了一个功能,无需重新创建。但是,有几点需要注意:
使用一些API反射来检查功能,可以在支持设备上使用此功能。但是,您仍然需要回退以重新创建其余的上下文。在我看来,在更多设备运行Android 3之前,最好暂缓使用setPreserveEGLContextOnPause
,并专注于确保上下文娱乐方法得到充分测试。
答案 1 :(得分:8)
如上面的评论所述,也可以避免在早期的Android版本(1.x,2.x)中删除GL上下文,解决方案是从Android-15 SDK源代码复制GLSurfaceView,更改其包名称,然后使用您自己的GlSurfaceView副本。
它适用于支持多种GL上下文的设备(目前除Adreno芯片外),无论Android版本如何。需要注意的是,Android-15的GLSurfaceView只包含与android-15一起使用的必要内容,我们的版本必须处理所有操作系统版本。
我们使用我们自己实现的GlSurfaceView基于ReplicaIsland的副本,其中Chriss Pruit也使用了他自己的实现。
在我们的版本中,我们从SDK-15添加了setPreserveEGLContextOnPause,它允许保留GL上下文,例如运行android 2.3的nexus。
我们还改变了其他东西以满足我们的需求,这与此问题无关(例如支持它的手机上的32位渲染,否则为16位)。
我们的GlSurfaceView:http://pastebin.com/U4x5JjAr
这是原始的SDK-15版本的GlSurfaceView,其格式与上述http://pastebin.com/hziRmB3E相同(Android)风格(因此很容易比较并查看更改)
请记住通过调用以下方式启用上下文保存:
glSurfaceView.setPreserveEGLContextOnPause(true);
答案 2 :(得分:3)
从API级别11开始,您可以指定是否必须保留您的上下文。
来自doc:
public void setPreserveEGLContextOnPause (boolean preserveOnPause) 自:API Level 11
控制GLSurfaceView时是否保留EGL上下文 暂停并恢复。
如果设置为true,则可以保留EGL上下文 GLSurfaceView已暂停。是否实际保留了EGL上下文 是否取决于程序所在的Android设备 运行可以支持任意数量的EGL上下文。 必须支持只能支持有限数量的EGL上下文的设备 释放EGL上下文以允许多个应用程序 分享GPU。
如果设置为false,则EGL上下文将在释放时释放 GLSurfaceView暂停,并在GLSurfaceView时重新创建 恢复。
默认值为false。
参数preserveOnPause保留EGL 暂停时的上下文
答案 3 :(得分:0)
自从我使用OpenGL以来已经有一段时间了,它是桌面电脑上的标准排序,但我似乎记得标准的OpenGL不需要在上下文切换时重新加载纹理。当然,在这种情况下,这并没有真正的帮助。
假设必须重新加载纹理,问题就变成:你如何加快速度?然后问题就变成了,你在任何时候都需要多少纹理,你可以根据需要加载它们吗?它们的尺寸是多少?我记得两个版本的加载速度通常更快,但这也可能取决于OpenGL的实现和驱动程序。
我也听说过在不会被破坏的地方保留一个上下文,有点像这个帖子:opengles view switching problem