【问题标题】:How to preserve EGL context when pausing Android ndk app暂停 Android ndk 应用程序时如何保留 EGL 上下文
【发布时间】:2019-05-12 19:50:37
【问题描述】:

我正在尝试改进开放框架,以便在暂停和恢复我的游戏时保留 GL 上下文。这样我就不必在每次暂停后重新加载所有纹理。我不希望你知道 openframeworks 代码,我会独立地解释我的问题。

我有一个 java 活动,它加载一个 main_layout.xml 文件,其中一个 RelativeLayout 在另一个 RelativeLayout 中。然后我实例化一个 GLSurfaceView 并使用 glContainer.addView(glView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); 将它添加到内部的 RelativeLayout。在 onPause 函数中,我在 GLSurfaceView 上调用 glView.onPause();,在 onResume 中,我在 GLSurfaceView 上调用 glView.onResume();

此代码有效,但它破坏了 onPause 中的 gl 表面(GLSurfaceView.surfaceDestroyed 在我的 GLSurfaceView 上被调用,它被扩展到 OFGLSurfaceView,以便我可以拦截此调用)。

为了解决这个问题,我在 GLSurfaceView 的初始化中添加了对 GLSurfaceView.setPreserveEGLContextOnPause 的调用,参数为“true”。现在我在暂停和恢复游戏后只看到黑屏。我发现,我可以通过从父 RelativeLayout 中删除 GLSurfaceView 并立即将其添加回 onResume 函数来解决此问题:glContainer.removeView( glView ); glContainer.addView( glView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) );。然而,这会再次破坏 gl 表面并迫使我重新加载纹理。

RelativeLayouts 或 GLSurfaceView 中的任何一个都没有重新实例化(我通过查看代码进行检查,然后使用 System.identityHashCode 检查这些实例的身份)。

main_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
   <RelativeLayout android:id="@+id/relativeLayout1" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android">
        <RelativeLayout android:id="@+id/of_gl_surface_container" android:layout_width="fill_parent" android:layout_height="fill_parent"/>
        <!-- add here other views' layouts -->
    </RelativeLayout>

OFAndroidLifeCycle.java 中处理从 Activity 接收到的事件的代码:

public static void glCreateSurface()
{
    if(mGLView == null)
    {
        mGLView = new OFGLSurfaceView(m_activity);

        OFGLSurfaceView glView = getGLView();

        glView.setPreserveEGLContextOnPause( true );

        ViewGroup parent = (ViewGroup)glView.getParent();
        if( parent == null )
        {
            ViewGroup glContainer = getActivity().getSurfaceContainer();
            glContainer.addView(glView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
        }
    }
}

public static void glPause()
{
    OFGLSurfaceView glView = getGLView();
    if( glView != null )
        glView.onPause();   
}

public static void glResume(ViewGroup glContainer)
{
    OFGLSurfaceView glView = getGLView();

    if( glView != null )
    {
        glView.onResume();

        glContainer.removeView( glView );
        glContainer.addView( glView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) );
    }
}

好吧,我只是感到困惑。有人可以详细说明这应该如何完成,有哪些陷阱或我应该尝试哪些方法?

谢谢。

【问题讨论】:

  • 一般来说这是不好的做法。电话用户可能打开了许多挂起的应用程序,并且应用程序在实际未运行时保留所有内存并不是“好”。这个模型的全部原因是为前台进程释放内存。
  • 我不会强迫手机将我的资源保存在内存中。一旦 Android 内存不足,它就可以随意杀死我的应用程序或直接破坏 EGL 上下文。我认为每次用户暂停然后恢复游戏以快速检查收到的电子邮件时花费 4 秒重新加载所有纹理的做法是更糟糕的做法。

标签: android opengl-es android-ndk egl


【解决方案1】:

我后来也在 gamedev.stackexchange.com 上创建了这个问题,今天我在那里发布了解决方案:

https://gamedev.stackexchange.com/questions/171908/how-to-preserve-egl-context-when-pausing-android-ndk-app

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-12
    • 1970-01-01
    • 2011-05-25
    • 1970-01-01
    • 1970-01-01
    • 2014-11-14
    • 2021-07-24
    相关资源
    最近更新 更多