简体   繁体   English

如何在暂停Android ndk应用程序时保留EGL上下文

[英]How to preserve EGL context when pausing Android ndk app

I am trying to improve openframeworks so that the GL context is preserved when pausing and resuming my game. 我正在尝试改进openframeworks,以便在暂停和恢复我的游戏时保留GL上下文。 So that I don't have to reload all textures after each pause. 因此,我不必在每次暂停后重新加载所有纹理。 I don't expect you to know openframeworks code, I'll explain my problem independent of it. 我不指望你知道openframeworks代码,我会独立解释我的问题。

I have java activity which loads a main_layout.xml file with a RelativeLayout inside another RelativeLayout. 我有java活动,在另一个RelativeLayout中加载一个带有RelativeLayout的main_layout.xml文件。 Then I instantiate a GLSurfaceView and add it to the inner RelativeLayout using glContainer.addView(glView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); 然后我实例化一个GLSurfaceView并使用glContainer.addView(glView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));将其添加到内部RelativeLayout glContainer.addView(glView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); . In onPause function, I call glView.onPause(); 在onPause函数中,我调用glView.onPause(); on GLSurfaceView and in onResume, I call glView.onResume(); 在GLSurfaceView和onResume中,我调用glView.onResume(); on GLSurfaceView. 在GLSurfaceView上。

This code works but it destroys the gl surface in onPause (GLSurfaceView.surfaceDestroyed gets called on my GLSurfaceView, which is extended to OFGLSurfaceView, so that I can intercept this call). 这段代码可以工作,但它会破坏onPause中的gl表面(GLSurfaceView.surfaceDestroyed会在我的GLSurfaceView上调用,它扩展到OFGLSurfaceView,这样我就可以拦截这个调用)。

To fix this, I added call to GLSurfaceView.setPreserveEGLContextOnPause with param 'true' to initialization of my GLSurfaceView. 为了解决这个问题,我添加了对GLSurfaceView.setPreserveEGLContextOnPause的调用,使用参数'true'来初始化我的GLSurfaceView。 Now I see only black screen after pausing and resuming the game. 现在,在暂停和恢复游戏后,我只看到黑屏。 I found out, that I can fix this by removing the GLSurfaceView from parent RelativeLayout and adding it back right away in onResume function: glContainer.removeView( glView ); glContainer.addView( glView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) ); 我发现,我可以通过从父RelativeLayout中删除GLSurfaceView并在onResume函数中立即添加它来解决这个问题: glContainer.removeView( glView ); glContainer.addView( glView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) ); glContainer.removeView( glView ); glContainer.addView( glView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) ); . This however destroys the gl surface again and forces me to reload textures. 然而,这会再次破坏gl表面并迫使我重新加载纹理。

There are no reinstantiations of either one of the RelativeLayouts or the GLSurfaceView (I checked it by looking at the code and then checking identities of those instances with System.identityHashCode). 没有任何一个RelativeLayouts或GLSurfaceView的重新实现(我通过查看代码然后使用System.identityHashCode检查这些实例的身份来检查它)。

main_layout.xml: 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>

Code in OFAndroidLifeCycle.java which handles events received from Activity: 处理从Activity接收的事件的OFAndroidLifeCycle.java中的代码:

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) );
    }
}

Well, I am just confused. 好吧,我只是困惑。 Can someone elaborate a bit about how this should be done, what are some pitfalls or what approaches should I try? 有人可以详细说明应该如何做,有什么陷阱或我应该尝试什么方法?

Thanks. 谢谢。

I later also created this question on gamedev.stackexchange.com and today I posted the solution there: 我后来也在gamedev.stackexchange.com上创建了这个问题,今天我在那里发布了解决方案:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM