暂停 Android ndk 应用程序时如何保留 EGL 上下文
How to preserve EGL context when pausing Android ndk app
我正在尝试改进 openframeworks,以便在暂停和恢复我的游戏时保留 GL 上下文。这样我就不必在每次暂停后重新加载所有纹理。我不希望你了解 openframeworks 代码,我会独立于它解释我的问题。
我有 java activity 加载一个 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.setPreserveEGLContextOnPause 的调用和参数 'true' 来初始化我的 GLSurfaceView。现在我在暂停和恢复游戏后只看到黑屏。我发现,我可以通过从父 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) );
}
}
好吧,我只是很困惑。有人可以详细说明应该如何完成这项工作,有哪些陷阱或我应该尝试哪些方法?
谢谢。
我后来也在 gamedev.stackexchange.com 上创建了这个问题,今天我在那里发布了解决方案:
我正在尝试改进 openframeworks,以便在暂停和恢复我的游戏时保留 GL 上下文。这样我就不必在每次暂停后重新加载所有纹理。我不希望你了解 openframeworks 代码,我会独立于它解释我的问题。
我有 java activity 加载一个 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.setPreserveEGLContextOnPause 的调用和参数 'true' 来初始化我的 GLSurfaceView。现在我在暂停和恢复游戏后只看到黑屏。我发现,我可以通过从父 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) );
}
}
好吧,我只是很困惑。有人可以详细说明应该如何完成这项工作,有哪些陷阱或我应该尝试哪些方法?
谢谢。
我后来也在 gamedev.stackexchange.com 上创建了这个问题,今天我在那里发布了解决方案: