防止onPause破坏OpenGL Context

时间:2010-01-21 20:47:28

标签: android opengl-es

我正在编写一个使用OpenGL ES(GLSurfaceView和GLSurfaceView.Renderer)的Android应用程序。问题是当用户切换应用程序然后切换回我的应用程序时,GLSurfaceView会破坏并重新创建GL上下文。这是根据文档应该做的,但有没有办法防止这种情况发生?

将纹理加载到上下文中需要很长时间,我希望不必重新加载它们。

4 个答案:

答案 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提供了一个功能,无需重新创建。但是,有几点需要注意:

  1. 目前市场上的approx. 90% of devices无法使用Android 3.x功能
  2. 这些设备还必须支持多个EGL上下文,目前还不清楚市场上有多少设备支持这种设备。
  3. 使用一些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